Webアプリケーションでのクライアント証明書情報の取得

2005-07-03T19:00+09:00 matsu
Tomcat上のWebアプリケーションでクライアント証明書情報を取得する方法を調査してみた.
概要
環境設定
Webアプリケーションでのクライアント証明書情報を取得方法

概要

ApacheとTomcatをmod_jkにて連係しているシステムで,Tomcat上のWebアプリケーションがクライアント証明書情報を取得する方法を調査する. クライアント認証はApacheにて行い,Webアプリケーション到達時には認証済とする. Webアプリケーションはリクエスト上のクライアント認証情報を取得して,それからクライアントを識別,特定し,Webアプリケーション上での権限などを設定するといった応用ができる. 本頁では,既にTomcatとmod_jkの連係はできているものとして,そこにクライアント認証のための設定をする方法を記述する.

環境設定

httpd.confにてmod_jkの設定を追加する. JaJakartaによると,Apacheがクライアント認証して,それに関連するデータをTomcatに転送する際にはいくつかの設定が必要らしい. まず,SSL関連の設定として,以下を記述する.
<VirtualHost sslthor.fireproject.jp:443>
SSLEngine on
SSLCertificateFile      /etc/apache/ssl.crt/server.crt
SSLCertificateKeyFile   /etc/apache/ssl.key/server.key
SSLVerifyClient require
SSLCACertificateFile    /etc/apache/ssl.cacrt/cacert.pem
SSLLog /var/log/apache/ssl_engine.log
SSLLogLevel info

SSLOptions +FakeBasicAuth +StdEnvVars +ExportCertData

ServerAdmin matsu@fireproject.jp
DocumentRoot /home/matsu/protected_html/
</VirtualHost>
SSLOptionsが今回の追加である. 特にExportCertDataが証明書の転送の指定らしい. 次にmod_jkの設定を追記する.
JkWorkersFile /etc/libapache-mod-jk/workers.properties
JkLogFile /var/log/apache/mod_jk.log
JkLogLevel error
JkMount /fireproject fp1
JkMount /fireproject/* fp1
JkExtractSSL On
JkHTTPSIndicator HTTPS
JkSESSIONIndicator SSL_SESSION_ID
JkCIPHERIndicator SSL_CIPHER
JkCERTSIndicator SSL_CLIENT_CERT
最後の5つが今回追加した設定である. どれもデフォルトの値でよいので,別に記述しなくてもよいようだ. あとはApacheを再起動して準備完了である.

Webアプリケーションでのクライアント証明書情報を取得方法

リクエストからクライアント証明書情報を取得して表示するサンプルJSPを作成してみた.

<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ page import = "java.security.cert.X509Certificate" %>
<%@ page import = "java.util.Enumeration" %>

<%

X509Certificate certs[] =
(X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
if (certs != null) {
  out.println ("certs num = " + certs.length);
  for (int i = 0; i < certs.length; i++) {
    X509Certificate cert = certs[i];
    out.println("<ul>");
    out.println("<li>");
    out.println("SerialNumber = [" + cert.getSerialNumber() + "]");
    out.println("<li>");
    out.println("notBefore = [" + cert.getNotBefore() + "]");
    out.println("<li>");
    out.println("notAfter = [" + cert.getNotAfter() + "]");
    out.println("<li>");
    out.println("IssuerDN = [" + cert.getIssuerDN() + "]");
    out.println("<li>");
    out.println("SubjectDN = [" + cert.getSubjectDN() + "]");
    out.println("</ul>");
  }
} else {
  out.println ("no Certificate");
}

out.println("<table border=4>");
out.println("<tr><th>KEY</th><th>VALUE</th></tr>");
for (Enumeration enum = request.getAttributeNames();
     enum.hasMoreElements();) {
     String key = (String)enum.nextElement();
     out.println("<tr><td>");
     out.println(key);
     out.println("</td><td>");
     out.println(request.getAttribute(key));
     out.println("</td></tr>");
}
out.println("</table>");

out.println(request.getRequestedSessionId());
out.println("<br/>");
%>
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ page import = "java.security.cert.X509Certificate" %>
<%@ page import = "java.util.Enumeration" %>

<%

X509Certificate certs[] =
(X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
if (certs != null) {
  out.println ("certs num = " + certs.length);
  for (int i = 0; i < certs.length; i++) {
    X509Certificate cert = certs[i];
    out.println("<ul>");
    out.println("<li>");
    out.println("SerialNumber = [" + cert.getSerialNumber() + "]");
    out.println("<li>");
    out.println("notBefore = [" + cert.getNotBefore() + "]");
    out.println("<li>");
    out.println("notAfter = [" + cert.getNotAfter() + "]");
    out.println("<li>");
    out.println("IssuerDN = [" + cert.getIssuerDN() + "]");
    out.println("<li>");
    out.println("SubjectDN = [" + cert.getSubjectDN() + "]");
    out.println("</ul>");
  }
} else {
  out.println ("no Certificate");
}

out.println("<table border=4>");
out.println("<tr><th>KEY</th><th>VALUE</th></tr>");
for (Enumeration enum = request.getAttributeNames();
     enum.hasMoreElements();) {
     String key = (String)enum.nextElement();
     out.println("<tr><td>");
     out.println(key);
     out.println("</td><td>");
     out.println(request.getAttribute(key));
     out.println("</td></tr>");
}
out.println("</table>");

out.println(request.getRequestedSessionId());
out.println("<br/>");
%>

certs num = 1

  • SerialNumber = [2]
  • notBefore = [Sun Jul 03 13:50:05 JST 2005]
  • notAfter = [Mon Jul 03 13:50:05 JST 2006]
  • IssuerDN = [EMAILADDRESS=matsu-ca@fireproject.jp, CN=thor.fireproject.jp, OU=CA, O=FIREPROJECT, L=SOMEWHERE-SI, ST=SOMEWHERE-KEN, C=JP]
  • SubjectDN = [EMAILADDRESS=matsu-client@fireproject.jp, CN=client.fireproject.jp, OU=CLIENT, O=FIREPROJECT, L=SOMEWHERE-SI, ST=SOMEWHERE-KEN, C=JP]
KEYVALUE
javax.servlet.request.cipher_suiteDHE-RSA-AES256-SHA
javax.servlet.request.X509Certificate[Ljava.security.cert.X509Certificate;@258c74

A71C43F0362B8E525AA6542764BF9260

This article was written by Fujiko