程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> tomcat配置SSL雙向認證,tomcat配置ssl

tomcat配置SSL雙向認證,tomcat配置ssl

編輯:JAVA綜合教程

tomcat配置SSL雙向認證,tomcat配置ssl


一、SSL簡單介紹

       SSL(Secure Sockets Layer 安全套接層)就是一種協議(規范),用於保障客戶端和服務器端通信的安全,以免通信時傳輸的信息被竊取或者修改。

     客戶端和服務器端在進行握手(客戶端和服務器建立連接和交換參數的過程稱之為握手)時會產生一個“對話密鑰”(session key),用來加密接下來的數據傳輸,解密時也是用的這個“對話密鑰”,而這個“對話密鑰”只有客戶端和服務器端知道。也就是說只要這個“對話密鑰”不被破解,就能保證安全。

  2. 客戶端證書和服務器端證書

    客戶端證書和服務器端證書用於證明自己的身份,就好比每個人都有一張身份證,這種身份證是唯一的。一般來說,只要有服務器端的證書就可以了,但是有時需要客戶端提供自己的證書,已證明其身份。

二、生成自簽名的服務器端證書和導入服務器端信任證書庫

    一般證書可以使用權威機構頒發的證書,如:veri sign,百度使用的就是veri sign頒發的證書,這樣的權威證書機構是受信任的,但是這些機構頒發的證書往往是需要收費的,這樣的證書也難得到。對於小型企業來說為了節約成本,常常使用自簽名的證書。   

    接下來使用JDK keytool工具來簽發證書,如果未安裝JDK,請先安裝JDK(本文使用的是JDK7)。本文所有的證書文件都放到F:\ca,您可以選擇一個目錄來存放。

          keytool -genkeypair -v -alias server -keyalg RSA -validity 3650 -keystore ./server.keystore  -storepass 123456 -keypass 123456 -dname "CN=127.0.0.1,OU=rm,O=rm,L=gz,ST=gd,C=cn"

         注意:-dname參數中的CN應該為服務器所在的ip或者域名

   

  2. 導出服務器端證書

    keytool -exportcert -alias server  -keystore ./server.keystore  -file ./server.cer  -storepass 123456

     

  3. 將服務器端證書導入信任證書

    keytool -importcert -alias serverca  -keystore ./server_trust.keystore  -file ./server.cer  -storepass 123456

     

三、生成客戶端證書並導入到服務器端信任證書庫

     keytool -genkeypair -v -alias client -dname "CN=rorymo" -keyalg RSA -validity 3650 -keypass 123456 -keystore ./client.p12 -storepass 123456 -storetype PKCS12

     

  2. 導出客戶端證書

    keytool -exportcert -alias client -file ./client.cer -keystore ./client.p12 -storepass 123456 -storetype PKCS12

    

  3. 導入客戶端證書到服務器端信任證書庫

    keytool -importcert -alias clientca  -keystore ./server_trust.keystore  -file ./client.cer  -storepass 123456

   

  4. 查看服務器端信任證書庫的信任證書信息

    keytool -list -keystore ./server_trust.keystore -storepass 123456

     

   可以看到信任證書庫中已經導入了一張服務器端證書和一張客戶端證書

  5. 至此我們已經生成了如下的文件

  

四、配置tomcat和web應用   

          將上圖的server.keystore和server_trust.keystore放到tomcat的根目錄下,例如我的tomcat目錄為:F:\ca\apache-tomcat-7.0.64

    

  2. 配置tomcat

   編輯conf/server.xml文件加入如下的配置:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="true" sslProtocol="TLS"
               keystoreFile="${catalina.base}/server.keystore" keystorePass="123456"
               truststoreFile ="${catalina.base}/server_trust.keystore" truststorePass="123456"/>

     說明:

  • clientAuth為true表示開啟SSL雙向認證
  • keystoreFile指定服務器端的證書位置
  • truststoreFile指定服務器端信任證書庫

  3. 編寫用來獲取客戶端證書的servlet

 1 package com.rorymo.demo.ssl;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 import java.security.cert.X509Certificate;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.annotation.WebServlet;
 9 import javax.servlet.http.HttpServlet;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletResponse;
12 
13 /**
14  * 
15  * SSLServlet
16  * 
17  * @author rorymo
18  * @version 1.0
19  */
20 @WebServlet("/SSLServlet")
21 public class SSLServlet extends HttpServlet {
22 
23     private static final long serialVersionUID = 1601507150278487538L;
24     private static final String REQUEST_ATTR_CERT = "javax.servlet.request.X509Certificate";
25     private static final String CONTENT_TYPE = "text/plain;charset=UTF-8";
26     private static final String DEFAULT_ENCODING = "UTF-8";
27     private static final String SCHEME_HTTPS = "https";
28 
29     public void doGet(HttpServletRequest request, HttpServletResponse response)
30             throws ServletException, IOException {
31         response.setContentType(CONTENT_TYPE);
32         response.setCharacterEncoding(DEFAULT_ENCODING);
33         PrintWriter out = response.getWriter();
34         X509Certificate[] certs = (X509Certificate[]) request.getAttribute(REQUEST_ATTR_CERT);
35         if (certs != null) {
36             int count = certs.length;
37             out.println("共檢測到[" + count + "]個客戶端證書");
38             for (int i = 0; i < count; i++) {
39                 X509Certificate cert = certs[i];
40                 out.println("客戶端證書 [" + cert.getSubjectDN() + "]: ");
41                 out.println("證書是否有效:" + (verifyCertificate(cert) ? "是" : "否"));
42                 out.println("證書詳細信息:\r" + cert.toString());
43             }
44         } else {
45             if (SCHEME_HTTPS.equalsIgnoreCase(request.getScheme())) {
46                 out.println("這是一個HTTPS請求,但是沒有可用的客戶端證書");
47             } else {
48                 out.println("這不是一個HTTPS請求,因此無法獲得客戶端證書列表 ");
49             }
50         }
51         out.close();
52     }
53 
54     public void doPost(HttpServletRequest request, HttpServletResponse response)
55             throws ServletException, IOException {
56         doGet(request, response);
57     }
58     
59     /**
60      * 
61      * 校驗證書是否過期
62      * 
63      * 
64      * @param certificate
65      * @return
66      */
67     private boolean verifyCertificate(X509Certificate certificate) {
68         boolean valid = true;
69         try {
70             certificate.checkValidity();
71         } catch (Exception e) {
72             e.printStackTrace();
73             valid = false;
74         }
75         return valid;
76     }
77 
78 }

 

 

  4. 在web應用的web.xml中加入如下配置

  <security-constraint>

    <web-resource-collection>

      <web-resource-name>SSL</web-resource-name>

      <url-pattern>/SSLServlet</url-pattern>

    </web-resource-collection>

    <user-data-constraint>

      <description>SSL required</description>

      <transport-guarantee>CONFIDENTIAL</transport-guarantee>

    </user-data-constraint>

  </security-constraint>

  說明:

  • 如果不加入這個配置,那麼所有訪問的地址都必須要使用SSL才能訪問,有時我們可能只需要通過某個或者某些SSL地址獲取客戶端證書來認證用戶身份,認證成功後不需要使用SSL來進行訪問。(可以配置多個security-constraint)
  • url-pattern:指定需要SSL才能進行訪問的地址
  • transport-guarantee:合法值為NONE、 INTEGRAL或CONFIDENTIAL,transport-guarantee為NONE值將對所用的通訊協議不加限制。INTEGRAL值表示數據必須以一種防止截取它的人閱讀它的方式傳送。雖然原理上(並且在未來的HTTP版本中),在 INTEGRAL和CONFIDENTIAL之間可能會有差別,但在當前實踐中,他們都只是簡單地要求用SSL
  • 創建SSLServlet獲取客戶端證書

五、測試

      

  由於我們這裡是雙向認證,所以也需要客戶端的證書,我們接下來導入客戶端證書:

  • 雙擊client.p12

  

  • 點擊下一步

   

  • 一直點擊下一步直到完成證書安裝(按照提示進行操作即可)
  •  查看安裝的客戶端證書,由於我使用的Google Chrome浏覽器(其他浏覽器可能不同),設置 -> 高級設置 -> 管理證書

   

 

  

 

  2. 重新訪問上面的地址:http://127.0.0.1:8080/SSL/SSLServlet

    

  浏覽器提示選擇客戶端證書進行認證,我們點擊【確定】,打開了一個警告頁面,提示我們服務端證書不受信任

  

 

 

  而且地址欄的圖標有個小紅叉:

    

  當然我們直接點擊是能打開的

  

   為了不出現這樣的警告信息,我們可以導入服務器端證書到客戶端

  a. 導入服務器端證書到客戶端

    •  雙擊server.cer

       

    • 點擊安裝證書,然後選擇證書的存儲位置“受信任的根證書頒發機構”,一直點擊下一步直到完成

      

 

    • 查看我們安裝的服務器端證書

       

 

  b. 關閉浏覽器,我們再訪問

六、附錄

    • -genkeypair在用戶主目錄中創建一個默認文件”.keystore”,還會產生一個mykey的別名,mykey中包含用戶的公鑰、私鑰和證書(在沒有指定生成位置的情況下,keystore會存在用戶系統默認目錄)
    • -alias 產生別名 每個keystore都關聯這一個獨一無二的alias,這個alias通常不區分大小寫
    • -keystore 指定密鑰庫的路徑(產生的各類信息將不在.keystore文件中)
    • -keyalg 指定密鑰的算法 (如 RSA,DSA,默認值為:DSA)
    • -validity 指定創建的證書有效期多少天(默認 90)
    • -keysize 指定密鑰長度 (默認 1024
    • -storepass 指定密鑰庫的密碼(獲取keystore信息所需的密碼)
    • -keypass 指定別名條目的密碼(私鑰的密碼)
    • -dname 指定證書發行者信息 其中: “CN=名字與姓氏,OU=組織單位名稱,O=組織名稱,L=城市或區域名 稱,ST=州或省份名稱,C=單位的兩字母國家代碼”
    • -list 顯示密鑰庫中的證書信息如:keytool -list -v –keystore path/to/keystore  -storepass password
    • -v 顯示密鑰庫中的證書詳細信息
    • -exportcert 導出指定別名的證書,如:keytool - exportcert -alias theAlias  -keystore path/to/keystore  -file path/to/keystore/cert  -storepass pass
    • -file 參數指定導出到文件的文件名
    • -delete 刪除密鑰庫中某條目 keytool -delete -alias theAlias  -keystore path/to/keystore –storepass pass
    • -printcert 控制台打印證書的詳細信息,如:keytool -printcert  -file path/to/keystore/cert -v
    • -keypasswd 修改密鑰庫中指定條目口令 keytool -keypasswd -alias theAlias -keypass oldPass -new newPass -storepass keystorePass -keystore path/to/keystore
    • -storepasswd 修改keystore口令 keytool -storepasswd -keystore path/to/keystore -storepass oldPass -new newPass
    • -importcert 將已簽名數字證書導入密鑰庫 keytool -importcert -alias certAlias -keystore path/to/keystore  -file path/to/keystore/cert


  2.  本文源碼下載

 


【完】

 感謝您的閱讀

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved