Tomcat配置https详述

这两天研究了下Tomcat如何配置https,实现以https的方式访问我们的web service,下面就如何配置Tomcat以及在访问过程中出现的问题做个简单的总结。

 

首先说明下,我使用的Tomcat的版本是Version 7.0.22。

我们先找到Tomcat的官方参考文档中如何配置SSL:http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html,里面介绍了如何配置SSL的步骤,总得来说,首先生成keystore文件,步骤如下:

1.在windows命令行下输入

写道
%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

2. 接下来提示输入密码,可以使用Tomcat的默认值changeit,然后按照提示输入相关信息后确认,这里的别名tomcat可以自己定义,一般情况下,上面生成的.keystore文件会在你的${user.home}目录下。

 

然后,找到Tomcat下的server.xml文件,找到

<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<!--
<Connector
           port="8443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           clientAuth="false" sslProtocol="TLS"/>
-->

 把打开注释,加上两个属性

keystoreFile="${user.home}/.keystore" keystorePass="changeit"

其中,keystoreFile是生成的服务证书的位置,keystorePass是密码,如果你没输入密码,默认的是changeit。代码如下:

写道
<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
SSLEnabled="true"
maxThreads="200" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="E:/apache-tomcat-7.0.22/.keystore"
keystorePass="123456"/>

 到这里,我们的Tomcat部分就以配置完成了,当我把我的服务部署到Tomcat下面时,出现了下面的错误:

写道
send file exception:sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

 我们要想成功访问我们的web service还需下面的步骤。

上面的错误告诉我们没有找到验证路径,所以还要生成一个验证证书,我们只需要用下面的代码来帮助我们生成:

public class InstallCert {

    public static void main(String[] args) throws Exception {
        String host;
        int port;
        char[] passphrase;
        if ((args.length == 1) || (args.length == 2)) {
            String[] c = args[0].split(":");
            host = c[0];
            port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
            String p = (args.length == 1) ? "changeit" : args[1];
            passphrase = p.toCharArray();
        } else {
            System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
            return;
        }

        File file = new File("jssecacerts");
        if (file.isFile() == false) {
            char SEP = File.separatorChar;
            File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");
            file = new File(dir, "jssecacerts");
            if (file.isFile() == false) {
                file = new File(dir, "cacerts");
            }
        }
        System.out.println("Loading KeyStore " + file + "...");
        InputStream in = new FileInputStream(file);
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(in, passphrase);
        in.close();

        SSLContext context = SSLContext.getInstance("TLS");
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory
                .getDefaultAlgorithm());
        tmf.init(ks);
        X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
        context.init(null, new TrustManager[] { tm }, null);
        SSLSocketFactory factory = context.getSocketFactory();

        System.out.println("Opening connection to " + host + ":" + port + "...");
        SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
        socket.setSoTimeout(10000);
        try {
            System.out.println("Starting SSL handshake...");
            socket.startHandshake();
            socket.close();
            System.out.println();
            System.out.println("No errors, certificate is already trusted");
        } catch (SSLException e) {
            System.out.println();
            e.printStackTrace(System.out);
        }

        X509Certificate[] chain = tm.chain;
        if (chain == null) {
            System.out.println("Could not obtain server certificate chain");
            return;
        }

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        System.out.println();
        System.out.println("Server sent " + chain.length + " certificate(s):");
        System.out.println();
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = chain[i];
            System.out.println(" " + (i + 1) + " Subject " + cert.getSubjectDN());
            System.out.println("   Issuer  " + cert.getIssuerDN());
            sha1.update(cert.getEncoded());
            System.out.println("   sha1    " + toHexString(sha1.digest()));
            md5.update(cert.getEncoded());
            System.out.println("   md5     " + toHexString(md5.digest()));
            System.out.println();
        }

        System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
        String line = reader.readLine().trim();
        int k;
        try {
            k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
        } catch (NumberFormatException e) {
            System.out.println("KeyStore not changed");
            return;
        }

        X509Certificate cert = chain[k];
        String alias = host + "-" + (k + 1);
        ks.setCertificateEntry(alias, cert);

        OutputStream out = new FileOutputStream("jssecacerts");
        ks.store(out, passphrase);
        out.close();

        System.out.println();
        System.out.println(cert);
        System.out.println();
        System.out.println("Added certificate to keystore 'jssecacerts' using alias '" + alias
                + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 3);
        for (int b : bytes) {
            b &= 0xff;
            sb.append(HEXDIGITS[b >> 4]);
            sb.append(HEXDIGITS[b & 15]);
            sb.append(' ');
        }
        return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

        private final X509TrustManager tm;

        private X509Certificate[] chain;

        SavingTrustManager(X509TrustManager tm) {
            this.tm = tm;
        }

        public X509Certificate[] getAcceptedIssuers() {
            throw new UnsupportedOperationException();
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            throw new UnsupportedOperationException();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            this.chain = chain;
            tm.checkServerTrusted(chain, authType);
        }
    }

}

 然后,运行这个程序,运行程序时,需要输入参数,在Run Configure的Argument输入localhost:8443,Run,显示以下信息:

写道
Loading KeyStore C:\Program Files\Java\jdk1.6.0_10\jre\lib\security\cacerts...
Opening connection to localhost:8443...
Starting SSL handshake...

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1591)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1035)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:124)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1107)
at com.neusoft.mega.client.InstallCert.main(InstallCert.java:85)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:285)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:191)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at com.neusoft.mega.client.InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:178)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1027)
... 8 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:280)
... 14 more

Server sent 1 certificate(s):

1 Subject CN=localhost, OU=It, O=It, L=CH, ST=CH, C=86
Issuer CN=localhost, OU=It, O=It, L=CH, ST=CH, C=86
sha1 e4 88 87 2f 9f 22 08 14 3a b7 85 62 99 0a 11 92 2c 8b 08 5c
md5 5f d5 f1 6c d4 28 fc 8e 56 88 45 fa 27 67 18 eb

Enter certificate to add to trusted keystore or 'q' to quit: [1]

 在console下输入1,会输出一堆信息,最后出现一句:Added certificate to keystore 'jssecacerts' using alias 'localhost-1',说明我们的验证文件就生成了,这个文件会在我们的

%JAVA_HOME%/jre6/lib/security

下,文件名为jssecacerts。

到此为止,我们就可以正常通过https访问我们的web service了。

注意:

我开始第一次访问时,出现了:java.security.cert.CertificateException: No name matching localhost found错误,这个错误是说我们指定资源证书的CN与资源访问地址不匹配,在我们生成ketstore文件时,我们在输入您的名字和姓氏的名称与我们自愿的地址不一致。

写道
Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.

C:\Documents and Settings\user>keytool -genkey -alias tomcat -keyalg RSA
输入keystore密码:

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

比如说,而偶们的访问地址是https://localhost:8443/tomcat,那么我们资源证书的CN也为localhost。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值