Tomcat 自定義簽名證書生成與部署

參考博客

http://www.cnblogs.com/tyjsjl/p/3359255.htmlphp

Tomcat 虛擬主機或二級域名配置html

Tomcat 官方配置項java

1.SSL單向認證

1.關於JKS證書

生成CA簽名證書keystorenode

keytool -genkey -alias twt_server -keyalg RSA -keystore twt_server.jks -validity 3600 -storepass 123456

您的名字與姓氏是什麼?  [Unknown]:   android

您的組織單位名稱是什麼?  [Unknown]:  itian web

您的組織名稱是什麼?  [Unknown]:  itian算法

您所在的城市或區域名稱是什麼?  [Unknown]:  北京 apache

您所在的省/市/自治區名稱是什麼?  [Unknown]:  海淀 瀏覽器

該單位的雙字母國家/地區代碼是什麼?  [Unknown]:  cn tomcat

CN=zhang, OU=zhang, O=zhang, L=xian, ST=shanxi, C=cn是否正確?  [否]:  y

輸入 <zhy_server> 的密鑰口令    (若是和密鑰庫口令相同, 按回車):  

而後生成cer證書

keytool -export -alias ca_server  -file twt_server.cer -keystore twt_server.jks -storepass 123456
 

而後部署

<Connector SSLEnabled="true" acceptCount="100" clientAuth="false"
	    disableUploadTimeout="true" 
	    enableLookups="true" 
	    keystoreFile="conf/CA/twt_server.jks" 
	    keystorePass="123456" 
	    maxSpareThreads="75" 
	    maxThreads="200" 
	    minSpareThreads="5" 
	    port="443" 
	    protocol="org.apache.coyote.http11.Http11NioProtocol" 
	    scheme="https" 
	    secure="true" 
	    sslProtocol="TLSv1.2"
	    />

或者咱們新增一個新的服務

<Service name="MySSLService">

<Executor name="MySSLServiceTomcatThreadPool" namePrefix="MySSLService-exec-" maxThreads="200" minSpareThreads="4"/>


<Connector  
					connectionTimeout="20000" 
					port="443"
					redirectPort="8443"
					maxPostSize="2048"  #post請求最大數量,這裏是2M,若是是0,則沒有限制
					maxThreads="200"
					executor="MySSLServiceTomcatThreadPool"  #使用鏈接池
					protocol="org.apache.coyote.http11.Http11NioProtocol"
					scheme="https" 
					secure="true" 
					SSLEnabled="true"
					keystoreType="JKS" #證書類型
					keystoreFile="conf/CA/twt_server.jks"
					keystorePass="123456"
					clientAuth="false" 
					sslProtocol="TLSv1.2"
					/>
	
<Connector port="9009" protocol="AJP/1.3" redirectPort="8443" executor="MySSLServiceTomcatThreadPool" />


<Engine defaultHost="localhost" name="MySSLServiceEngine">
	

<Realm className="org.apache.catalina.realm.LockOutRealm">
       	 	<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>

</Realm>
		

<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
			<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="ssl_access_log" suffix=".txt"/>

</Host>


</Engine>

</Service>

這樣訪問,經過相應的url,如‍‍‍‍https就能訪問了.

 

2.關於部署PKCS12證書

這裏還有個問題,咱們生成的證書其實是JKS類型的證書,若是咱們使用PKCS12證書如何部署呢,PKCS12是互聯網標準,若是使用PKCS12,那麼java能夠更好地與其餘語言通訊。

JKS與PKCS12互相導入

p12(pfx) -> jks

keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks

jks -> p12(pfx)

keytool -importkeystore -srckeystore keystore.jks -srcstoretype JKS
-deststoretype PKCS12 -destkeystore keystore.p12

從jks裏面導出cert

keytool -export -alias cert0001 -keystore trust.jks -storepass 123456 -file cert0001.cer

將cert導入jks

keytool -import -v -alias cert001 -file cert001.cer -keystore trust.jks -storepass 123456 -noprompt

那麼,咱們能夠配置以下

<Connector
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           port="8443" maxThreads="200"
           scheme="https"  #使用https協議
           secure="true" #使用安全連接 
           SSLEnabled="true"
           keystoreFile="conf/CA/keystore.p12"  #指定PKCS12 keystore的位置
           keystoreType="PKCS12"  #證書類型修改成PKCS12便可
           keystorePass="123456" 
           clientAuth="false"    #不去校驗客戶端
           sslProtocol="TLS"/>

 

2.關於APR部署CA證書

APR能夠提高Tomcat性能,那麼APR的Connector如何配置SSL呢

<Connector      
                protocol="HTTP/1.1" 
                port="443" 
                 maxHttpHeaderSize="8192"
                 maxThreads="150"
                 enableLookups="false" 
                 disableUploadTimeout="true"
                 acceptCount="100" 
                 scheme="https" 
                 secure="true"
                 SSLEnabled="true"
                 SSLCertificateFile="conf/CA/rsa-private-key.pem"
                 SSLCertificateKeyFile="conf/CA/self-signed-cert.crt" />

注意,APR的CA證書須要經過openSSL生成

openssl genrsa -out rsa-private-key.pem 1024
openssl req -new -x509 -nodes -sha1 -days 365 -key rsa-private-key.pem -out self-signed-cert.crt

 

2.SSL雙向認證

1.生成服務器證書庫(爲了測試,我把有效期改成1天)

keytool -genkey -alias ca_server -keyalg RSA -keystore ca_server.jks -validity 1 -storepass 123456

注意:第一項提示姓名與姓氏時請輸入你的 域名

1.生成客戶端證書庫(爲了測試,我把有效期改成1天)

keytool -genkey -alias ca_client -keyalg RSA  -storetype PKCS12 -keystore ca_client.pfx -validity 1 -storepass 123456

客戶端(客戶端須要使用PKCS12的密鑰,所以這裏咱們生成pfx密鑰證書)

2.將客戶端證書部分添加到服務端證書庫(讓服務器信任客戶端

2.1.pkcs12不能直接導入服務器證書庫,須要導出cer證書,將證書導入到證書庫中

keytool -export -alias ca_client -keystore ca_client.pfx -storetype PKCS12 -storepass 123456  -rfc -file ca_client.cer

2.2而後將證書導入到服務端證書庫中

keytool -import -v  -alias ca_client -file  ca_client.cer -keystore ca_server.jks

 

3.配置Connector

在這裏,咱們爲了讓服務端證書庫和認證庫不要使用同一個keystore,咱們把ca_server.jks複製一份起名爲ca_trust.jks

此時配置修改以下

<Connector SSLEnabled="true" 
        acceptCount="100" 
	    disableUploadTimeout="true" 
	    enableLookups="true" 
	    maxSpareThreads="75" 
	    maxThreads="200" 
	    minSpareThreads="5" 
	    port="8848" 
	    protocol="org.apache.coyote.http11.Http11NioProtocol" 
	    scheme="https" 
	    secure="true" 
        clientAuth="true"  #設置爲true,不然不回去驗證客戶端
	    sslProtocol="TLSv1.2"
	    clientAuth="true"
        keystoreType="JKS"
        keystoreFile="conf/auth/ca_server.jks" 
	    keystorePass="123456" 
        truststoreType="JKS"
        truststoreFile="conf/auth/ca_trust.jks" 
        truststorePass="123456"
	    />

 

4.使用瀏覽器訪問出現限制

而後咱們啓動Tomcat,使用瀏覽器訪問,發現不能訪問。說明咱們的設置已經生效了,那麼想讓瀏覽器能訪問該如何作呢?

首先,咱們須要安裝咱們的pfx證書,雙擊安裝,存儲區域位置請選擇【我的,不然瀏覽器依然沒法訪問!

而後咱們訪問瀏覽器,就會出現證書選擇提示,選擇肯定,便能瀏覽網頁了。

5.Android雙向認證

雙向認證,以Android爲例子,Android支持PKCS12,BKS,AndroidCAStore,AndroidKeyStore

Name Supported (API Levels)
AndroidCAStore 14+(推薦)
AndroidKeyStore 18+ (推薦)
BCPKCS12 1–8 (不建議考慮)
BKS 1+ 
BouncyCastle 1+ 
PKCS12 1+ (推薦,PKCS12是互聯網標準)
PKCS12-DEF 1–8(不建議考慮)

咱們這裏用網上的代碼,BKS作例子,固然,pkcs12能夠參考 android https經過加載pfx證書獲取數據

public void setCertificates(InputStream... certificates)
{    try
    {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);        int index = 0;        for (InputStream certificate : certificates)
        {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));            try
            {                if (certificate != null)
                    certificate.close();
            } catch (IOException e)
            {
            }
        }

        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.
                getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);        //初始化keystore
        KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        clientKeyStore.load(mContext.getAssets().open("ca_client.bks"), "123456".toCharArray());

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, "123456".toCharArray());

        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
        
       HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
                     
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
        
        @Override
        public boolean verify(String hostname, SSLSession sslsession) {
       
        if("localhost".equals(hostname)){  
            return true;  
        } else {  
            return false;  
        }  
      }
  });

    } catch (Exception e)
    {
        e.printStackTrace();
    } 

}

讀取cer證書

CertificateFactory certificatefactory = CertificateFactory
				.getInstance("X.509");
		FileInputStream bais = new FileInputStream("srca.cer");
		X509Certificate Cert = (X509Certificate) certificatefactory
				.generateCertificate(bais);
		bais.close();
		System.out.println("版本號 " + Cert.getVersion());
		System.out.println("序列號 " + Cert.getSerialNumber().toString(16));
		System.out.println("全名 " + Cert.getSubjectDN());
		System.out.println("簽發者全名n" + Cert.getIssuerDN());
		System.out.println("有效期起始日 " + Cert.getNotBefore());
		System.out.println("有效期截至日 " + Cert.getNotAfter());
		System.out.println("簽名算法 " + Cert.getSigAlgName());
		byte[] sig = Cert.getSignature();
		System.out.println("簽名:" + new BigInteger(sig).toString(16));
		PublicKey pk = Cert.getPublicKey();
		System.out.println("PublicKey:"
		+ Base64.getEncoder().encodeToString(pk.getEncoded()));

若是從密鑰庫讀取

 String pass="080302";
 
          String alias="mykey";
 
          String name=".keystore";
 
          FileInputStream in=new FileInputStream(name);
 
          KeyStore ks=KeyStore.getInstance("JKS");           
 
          ks.load(in,pass.toCharArray());
 
          Certificate c=ks.getCertificate(alias);
 
          in.close();
 
         System.out.println(c.toString( ));

PHP部分參閱

http://php.net/manual/zh/ref.openssl.php

http://www.sunzhenghua.com/wamp-config-ssl-https

相關文章
相關標籤/搜索