2012-08-14 28 views
9

我使用一個帶客戶端認證的tomcat http連接器。如果客戶端啓動到我的服務器的新連接併發送他的證書,我可以獲取證書並從我的Java代碼中讀取傳入證書中的公用名稱。如果是,如何?在Tomcat中讀取傳入證書

感謝 ADI

+0

http://www.coderanch.com/t/438788/Security/Read-client-certificate-Servlet 目光投向後結束。祝你好運! – mazaneicha 2012-08-14 03:15:22

回答

16

您可以通過獲取javax.servlet.request.X509Certificate屬性您HttpServletRequest獲取客戶端證書鏈。這是一組X509Certificates,其中第一個(位置0)是實際的客戶端證書(如果需要中間CA證書,則鏈的其餘部分可能存在)。

X509Certificate certs[] = 
    (X509Certificate[])req.getAttribute("javax.servlet.request.X509Certificate"); 
// ... Test if non-null, non-empty. 

X509Certificate clientCert = certs[0]; 

// Get the Subject DN's X500Principal 
X500Principal subjectDN = clientCert.getSubjectX500Principal(); 

然後可以得到此主體(如CN)爲this answer描述的各種的RDN(相對專有名稱):

import javax.naming.ldap.LdapName; 
import javax.naming.ldap.Rdn; 

String dn = subjectDN.getName(); 
LdapName ldapDN = new LdapName(dn); 
for(Rdn rdn: ldapDN.getRdns()) { 
    System.out.println(rdn.getType() + " -> " + rdn.getValue()); 
} 

(你也可以使用BouncyCastle的的X509Name讓每個RDN。 )

在X.509證書中,主題DN是RDN的有序序列,每個RDN都是一組AVA(屬性值斷言),例如CN=...O=...。原則上,每個RDN可以有多個AVA,這會在這裏引起問題,但這是非常罕見的。你幾乎可以假設每個RDN只有一個AVA。 (也許this answer可能會感興趣。)

+0

感謝,一切工作非常出色,首先嚐試:-) 對於使用Axis2和不知道如何獲得HttpServletRequest的每個人: \t MessageContext的背景= MessageContext.getCurrentMessageContext(); \t HttpServletRequest requestProperty =(HttpServletRequest)context.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST); – adihubba 2012-08-15 00:32:43

+0

對於req.getAttribute(「javax.servlet.request.X509Certificate」),我得到空值。是否需要從相同的匹配域發送請求?我嘗試了本地(使用本地主機)機器和開發服務器。 – TechnoCrat 2017-12-27 07:12:34

+0

@TechnoCrat這可能意味着(a)您的服務器未配置爲請求/需要客戶端證書,或(b)在請求客戶端證書時發送的證書頒發機構列表與您擁有的任何客戶端證書不匹配在你的機器上。這不是關於「域」匹配,而是關於CA匹配。 – Bruno 2017-12-27 11:57:29

0

感謝mazaneicha:

 String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); 

     if (cipherSuite != null) { 
      X509Certificate certChain[] = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); 
      if (certChain != null) { 
       for (int i = 0; i < certChaNin.length; i++) { 
        System.out.println ("Client Certificate [" + i + "] = " 
          + certChain[i].toString()); 
       } 
      } 
     } 
+0

您不需要先獲取並測試密碼套件。 – Bruno 2012-08-14 11:25:13