序文
この記事では、OpenSSLは、相互認証を実現する自己署名証明書、HTTPSを生成することが記載されています。
まず、CA証明書、クライアント証明書を生成するためにOpenSSLを使用してLinuxで、サーバ証明書
ビューのOpenSSLのバージョン番号
openssl version -a
のOpenSSLインストールする必要はありません場合は
ダウンロード:www.openssl.org/source/openssl-1.0.2p.tar.gzは、
tar -zxv openssl-1.0.2p.tar.gz
cd openssl-1.0.2p/
./config
make && make install
./config shared
make clean
make && make install
1.、nginxのSSLディレクトリの下にディレクトリを作成し、SSLを入力し、次のスクリプトを実行し、最終的にクライアントのパスワードを入力してください
#!/bin/bash
# function: 创建 nginx https ,双向认证证书
#
# BEGIN
#
# 网站域名
# 在签发服务(客户)端证书的时候
# 这个域名必须跟 subj 中的 CN 对应
# 否则浏览器会报不安全的链接
# 查找所有javatest.hqxapp.com替换成域名运行即可
domain="javatest.hqxapp.com"
#
# ---------- CA ----------
#
# 准备CA密钥
echo "创建CA密钥.."
openssl genrsa -out $domain.CA.key 2048
# 生成CA证书请求
# 证书请求都是根据私钥来生成的
echo "生成CA证书请求.."
openssl req -new -key $domain.CA.key -out $domain.CA.csr -days 365 -subj /C=CN/ST=GuangDong/L=GuangZhou/O=javatest.hqxapp.com/OU=javatest.hqxapp.com/CN=opcenter/emailAddress=javatest.hqxapp.com -utf8
# 签名CA证书请求
# 使用自己的私钥来给这个CA证书请求签名
# 经过多次测试得知: 这个时间如何设置的太长,如 3650(10年)
# chrome浏览器会报, 该网站使用的安全设置已过期
# 所以https不会显示是绿色, 而是带一个黄色三角形的图标
# 奇怪的是: 如果设成1年,也就是365天,不会提示该网站使用的安全设置已过期
# 而且也是绿色的标识
# 但如果是2年, 也是绿色的标识,但是会提示该网站使用的安全设置已过期
# 这个应该chrome浏览器的问题
echo "创建CA证书.."
openssl x509 -req -in $domain.CA.csr -signkey $domain.CA.key -out $domain.CA.crt -days 365
# CA证书转换为DER格式,
# DER格式似乎更加通用
openssl x509 -in $domain.CA.crt -out $domain.CA.der -outform DER
# 现在, 终于拿到了自己做 CA 需要的几个文件了,
# 密钥: $domain.CA.key
# 证书: $domain.CA.crt
# 系统使用的: $domain.CA.der
# 接下来, 要创建一个网站, 就需要让 CA 给他签名一个证书了
#
# --------- SERVER ----------
#
# 准备网站密钥
echo "创建网站(服务端)密钥.."
openssl genrsa -out $domain.server.key 2048
# 生成网站证书请求
# CN 一定要是网站的域名, 否则会通不过安全验证
echo "生成网站(服务端)证书请求.."
openssl req -new -key $domain.server.key -out $domain.server.csr -days 365 -subj /C=CN/ST=GuangDong/L=GuangZhou/O=javatest.hqxapp.com/OU=javatest.hqxapp.com/CN=$domain/emailAddress=javatest.hqxapp.com -utf8
# CA签名网站证书请求
# 不是拿到 CA 的证书了就可以说自己是 CA 的, 最重要的是, 签名需要有 CA 密钥
# 如果客户端(个人浏览器)信任 CA 的证书的话, 那么他也就会信任由 CA 签名的网站证书
# 因此让浏览器信任 CA 的证书之后, 客户端就自然信任服务端了, 只要做单向认证的话, 到这一步证书这一类材料就已经准备好了
# 但是双向认证就还要给客户端(个人的浏览器)准备一份证书
# 让服务端可以知道客户端也是合法的。
# 假如让服务端也信任 CA 的证书
# 那 CA 签名的客户端证书也就能被信任了。
echo "通过CA证书签名, 创建网站(服务端)证书.."
openssl x509 -req -in $domain.server.csr -out $domain.server.crt -CA $domain.CA.crt -CAkey $domain.CA.key -CAcreateserial -days 365
#
# --------- CLIENT ----------
#
# 准备客户端私钥
echo "创建浏览器(客户端)密钥.."
openssl genrsa -out $domain.client.key 2048
# 生成客户端证书请求
echo "生成浏览器(客户端)证书请求.."
openssl req -new -key $domain.client.key -out $domain.client.csr -days 3650 -subj /C=CN/ST=GuangDong/L=GuangZhou/O=javatest.hqxapp.com/OU=javatest.hqxapp.com/CN=$domain/emailAddress=javatest.hqxapp.com -utf8
# CA签名客户端证书请求
echo "通过CA证书签名, 创建浏览器(客户端)证书.."
openssl x509 -req -in $domain.client.csr -out $domain.client.crt -CA $domain.CA.crt -CAkey $domain.CA.key -CAcreateserial -days 365
# 客户端证书转换为DER格式
openssl x509 -in $domain.client.crt -out $domain.client.der -outform DER
# 客户端证书转换为 PKCS, 即12格式
# 全称应该叫做 Personal Information Exchange
# 通常以 p12 作为后缀
echo "转换客户端证书为p12格式.."
openssl pkcs12 -export -in $domain.client.crt -inkey $domain.client.key -out $domain.client.p12
あなたは、スクリプトを実行する前に許可を与える必要があります。chmod 777 ssl.sh
証明書を生成します。
2. [設定nginxのでは
vim nginx/conf/nginx.conf
server {
listen 443;
server_name localhost;
ssi on;
ssi_silent_errors on;
ssi_types text/shtml;
ssl on;
ssl_certificate ../ssl/javatest.hqxapp.com.server.crt;
ssl_certificate_key ../ssl/javatest.hqxapp.com.server.key;
ssl_client_certificate ../ssl/javatest.hqxapp.com.CA.crt;
ssl_session_timeout 5m;
ssl_verify_client on;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
index index.html index.htm;
proxy_pass http://127.0.0.1:8080;
}
}
3.报错nginxの:[EMERG] /usr/local/nginx/conf/nginx.confで未知のディレクティブ「SSL」
理由:この設定nginxのSSL証明書は、SSLでこのモジュールを参照する必要がありますが、nginxの開始時刻のコンパイルがエラーになり、一緒にSSLモジュールに翻訳されていませんので。
ソリューション:
1に./configure --with-sslのhttp_ssl_module //このモジュールを再度追加
2 makeコマンドが、再カバー、その後全体のnginxをコンパイラが行うために使用されているので、make installを実行し、インストールするmake installをしておらず、 A。
我々は、コマンドを実行した後に行う3、我々はOBJSフォルダnginxの1つの以上のドキュメント、ディレクトリを抽出するためにnginxの中で見ることができ、これはプログラムの新バージョンです。まず、私たちは少しのバックアップnginxの前に置き、その後、新しいプログラムが過去に前にカバーすることができますコピーします。(ストップnginxのプログラム)
cp /usr/local/nginx/sbin/nginx
/usr/local/nginx/sbin/nginx.bak
cp objs/nginx /usr/local/nginx/sbin/nginx
4、最終的にはそこSSLモジュールが正常にインストールかどうかを確認するために、nginxのインストールディレクトリの下に来ました。実行は見に-Vを./sbin/nginx。
最後に、nginxの/ sbinに、。/ nginxの-s入力してリロード、 再起動nginxの。
第二には、(変更を伴う証明書(新しい証明書を生成する)、再起動nginxのに必要)のHTTPSアクセスにクライアント証明書を使用します
1.ブラウザ
、javatest.hqxapp.com.client.p12をダブルクリックして次のステップは、スクリプト生成された証明書、最終ステップ入力を実行したときに、パスワード中に入力されるように、パスワードを完了するまで、証明書をインストールします。その後、ブラウザを再起動してください。
証明書のアクセスをインストールしないでください、それは次のようなエラーが報告されます
2.郵便配達
検証する閉じます
キーを追加します。
リクエストインターフェイス
3. Javaコード
証明書を取得1.(をserver.crtはserver.bks換算しました)
キーツール-importcert -v -trustcacerts -alias TTT -file位置1 -keystore位置2 -storetype BKS -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath位置3 -storepass位置4
1つの位置:絶対パス証明書をserver.crtの
位置2は:で生成されるファイルの絶対パスをserver.bks
位置3:変換ジャーパッケージ絶対パス
セットに証明書パスワード:位置4
举例ます。keytool -importcert -v -trustcacerts -alias TTT -file C:\ Users \ユーザー20180030 \デスクトップ\ SSL \ javatest.hqxapp.com.server.crt -keystore C:\ Users \ユーザー20180030 \デスクトップ\ SSL \ javatest.hqxapp .com.server.bks -storetype BKS -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath D:\ SSL \ bcprov-jdk15on-163.jar -storepass密码
2.server.bks証明書はserver.jks証明書に変換しました
server.jks Javaの証明書は、サーバ証明書への最終使用です。
キーフォルダを作成するために、プロジェクトのルートディレクトリに2つの証明書ファイル。オープンportecle.jar、ツールを起動します。
オープンserver.bksファイルは
BKSにコマンド変換する際に、パスワードのセットを入力
変換JKS形式
として保存して、証明書のJKS取得
コールJavaコードを
package com.hqx.util;
import com.alibaba.fastjson.JSONObject;
import org.junit.Test;
import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Map;
public class HttpsClient {
public static String KEY_STORE_FILE="key/javatest.hqxapp.com.client.p12";
public static String KEY_STORE_PASS="密码";
/**
* server.crt转换bks,再转为jks格式
*/
public static String TRUST_STORE_FILE="key/javatest.hqxapp.com.server.jks";
public static String TRUST_STORE_PASS="密码";
private static SSLContext sslContext;
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
// 打开和URL之间的连接
if(connection instanceof HttpsURLConnection){
((HttpsURLConnection)connection)
.setSSLSocketFactory(getSSLContext().getSocketFactory());
}
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
//System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
if(connection.getResponseCode()==200){
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(),"utf8"));
}else{
in = new BufferedReader(new InputStreamReader(
connection.getErrorStream(),"utf8"));
}
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
if(conn instanceof HttpsURLConnection){
((HttpsURLConnection)conn)
.setSSLSocketFactory(getSSLContext().getSocketFactory());
}
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
if(conn.getResponseCode()==200){
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(),"utf8"));
}else{
in = new BufferedReader(
new InputStreamReader(conn.getErrorStream(),"utf8"));
}
String line="";
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
public static SSLContext getSSLContext(){
long time1=System.currentTimeMillis();
if(sslContext==null){
try {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(getkeyStore(),KEY_STORE_PASS.toCharArray());
KeyManager[] keyManagers = kmf.getKeyManagers();
TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(getTrustStore());
TrustManager[] trustManagers= trustManagerFactory.getTrustManagers();
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, new SecureRandom());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
long time2=System.currentTimeMillis();
System.out.println("SSLContext 初始化时间:"+(time2-time1));
return sslContext;
}
public static KeyStore getkeyStore(){
KeyStore keySotre=null;
try {
keySotre = KeyStore.getInstance("PKCS12");
File file = new File(KEY_STORE_FILE);
System.out.println(file.getAbsolutePath());
FileInputStream fis = new FileInputStream(new File(KEY_STORE_FILE));
keySotre.load(fis, KEY_STORE_PASS.toCharArray());
fis.close();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return keySotre;
}
public static KeyStore getTrustStore() throws IOException{
KeyStore trustKeyStore=null;
FileInputStream fis=null;
try {
trustKeyStore=KeyStore.getInstance("JKS");
fis = new FileInputStream(new File(TRUST_STORE_FILE));
trustKeyStore.load(fis, TRUST_STORE_PASS.toCharArray());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
fis.close();
}
return trustKeyStore;
}
@Test
public static void main(String[] args) throws UnsupportedEncodingException {
String result=sendGet("https://javatest.hqxapp.com/demo/", "");
System.out.println(result);
}
@Test
public void t() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("content", "111");
String result=sendPost("https://javatest.hqxapp.com/demo/", jsonObject.toJSONString());
System.out.println(result);
}
}
ジャーパッケージ、スクリプト上で使用し、コードがリソースモジュールからダウンロードすることができます。
CSDNます。https://blog.csdn.net/qq_27682773
ジェーン帳します。https://www.jianshu.com/u/e99381e6886eが
します。https://www.cnblogs.com/lixianguoパークブログ
個人的なブログします。https:// www.lxgblog.com