Tomcat 自定义签名证书生成与部署

1.SSL单向认证

1.关于JKS证书

生成CA签名证书keystore

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

您的名字与姓氏是什么?  [Unknown]:  

您的组织单位名称是什么?  [Unknown]:  itian

您的组织名称是什么?  [Unknown]:  itian

您所在的城市或区域名称是什么?  [Unknown]:  北京

您所在的省/市/自治区名称是什么?  [Unknown]:  海淀

该单位的双字母国家/地区代码是什么?  [Unknown]:  cn

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

输入 <zhy_server> 的密钥口令    (如果和密钥库口令相同, 按回车):  

然后生成cer证书

keytool -export -alias twt_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

NameSupported (API Levels)
AndroidCAStore14+(推荐)
AndroidKeyStore18+ (推荐)
BCPKCS121–8 (不建议考虑)
BKS1+ 
BouncyCastle1+ 
PKCS121+ (推荐,PKCS12是互联网标准)
PKCS12-DEF1–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( ));

转载自:https://my.oschina.net/ososchina/blog/500973?p=1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值