zoukankan      html  css  js  c++  java
  • java https tomcat 单双认证(含证书生成和代码实现) 原创转载请备注,谢谢O(∩_∩)O

    server: apache-tomcat-6.0.44 jdk1.7.0_79
    client: jdk1.7.0_79

    jks是JAVA的keytools证书工具支持的证书私钥格式。 pfx是微软支持的私钥格式。 cer是证书的公钥。

    生成:
        keytool -genkey -alias tbb -keyalg RSA -keystore D:cert	bb.keystore
        模板:
         keytool -genkey -alias yushan -keypass yushan -keyalg RSA -keysize 1024 -validity 365((默认为90天)) -keystore D:cert	bb.keystore -storepass 123456 -dname "CN=(名字与姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称), ST=(州或省份名称), C=(单位的两字母国家代码)";(中英文即可)
    验证:
        keytool -selfcert -alias tbb -keystore D:cert	bb.keystore
    导出:    
        keytool -export -alias tbb -keystore D:cert	bb.keystore -storepass 12345678 -rfc -file D:cert	bb.cer
    转换    cer -> jks
        keytool -import -alias mycert -file D:cert	bb.cer -keystore D:cert	bb.jks  
    
    keystore信息的查看:
         打印证书的 MD5 指纹
        keytool -list  -v -keystore D:cert	bb.keystore -storepass 12345678
        可打印的编码格式输出证书
        keytool -list  -rfc -keystore D:cert	bb.keystore -storepass 12345678
    生成客户端证书库
    keytool -validity 36500 -genkeypair -v -alias client -keyalg RSA -storetype PKCS12 -keystore D:certclient.p12 -dname "CN=spring,OU=jiajianfa,O=jiajianfa,L=Wuhan,ST=HuBei,c=cn" -storepass 12345678 -keypass 12345678
    从客户端证书库中导出客户端证书
    keytool -export -v -alias client -keystore D:certclient.p12 -storetype PKCS12 -storepass 12345678 -rfc -file D:certclient.cer
    
    将客户端证书导入到服务器证书库(使得服务器信任客户端证书,服务器端用此验证客户端的合法性)
    keytool -import -v -alias client -file D:certclient.cer -keystore D:cert	bb.keystore -storepass 12345678
    
    查看服务端证书中信任的客户端证书
    keytool -list -keystore D:cert	bb.keystore  -storepass 12345678

    tomcat server.xml 配置:

    <!-- clientAuth  true:双向认证   false:单向认证-->
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
                   maxThreads="150" scheme="https" secure="true"
                   clientAuth="true" sslProtocol="TLS"  keystorePass="12345678" keystoreFile="D:cert	bb.keystore"
                   truststoreFile="D:cert	bb.keystore" truststorePass="12345678"  />
    <!--  配置服务端项目web.xml  在<welcome-file-list>之后增加:-->

    <!-- 强制SSL配置,即普通的请求也会重定向为SSL请求 --> <security-constraint> <web-resource-collection> <web-resource-name>SSL</web-resource-name> <url-pattern>/*</url-pattern><!-- 全站使用SSL <url-pattern>/*</url-pattern>--> </web-resource-collection> <user-data-constraint> <description>SSL required</description> <!-- CONFIDENTIAL: 要保证服务器和客户端之间传输的数据不能够被修改,且不能被第三方查看到 --> <!-- INTEGRAL: 要保证服务器和client之间传输的数据不能够被修改 --> <!-- NONE: 指示容器必须能够在任一的连接上提供数据。(即用HTTP或HTTPS,由客户端来决定)--> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>

    单向认证:

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Authenticator;
    import java.net.InetSocketAddress;
    import java.net.PasswordAuthentication;
    import java.net.Proxy;
    import java.net.URL;
    import java.util.Date;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLSession;
    
    /**
     * @Description https单向认证
     * @author sprinng
     *
     */
    public class ClientSendDataSingle {
        /**
         * 
         * @param sendurl 请求地址
         * @param res  返回结果
         * @param sendData 参数
         * @param timeOut  超时时间(min)
         * @param useProxy  是否使用代理
         * @param trustStorePath 证书路径
         * @param trustStorePwd 证书密码
         * @return
         * @throws Exception
         */
        public static String send(String sendurl, String res, String sendData, String timeOut, boolean useProxy, String trustStorePath, String trustStorePwd)throws Exception {
            System.setProperty("javax.net.ssl.trustStore", trustStorePath);
            System.setProperty("javax.net.ssl.trustStorePassword", trustStorePwd);
            URL url = new URL(sendurl);
            HttpsURLConnection connection = null;
            HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName, SSLSession session) {
                    return true;
                }
            };
            System.setProperty("java.protocol.handler.pkgs","sun.net.www.protocol");
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
            Date current = new Date(System.currentTimeMillis());
            System.out.println("begint to open connection at " + current);
            //使用代理
            if(useProxy){
                InetSocketAddress isa = new InetSocketAddress(PropertiesUtil.properties.getProperty("proxy_host"), Integer.parseInt(PropertiesUtil.properties.getProperty("proxy_port")));
                Proxy proxy = new Proxy(Proxy.Type.HTTP, isa);
                Authenticator.setDefault(new MyAuthenticator(PropertiesUtil.properties.getProperty("proxy_user"), PropertiesUtil.properties.getProperty("proxy_password")));
                connection = (HttpsURLConnection) url.openConnection(proxy);
            }else{
                connection = (HttpsURLConnection) url.openConnection();
            }
            Date end = new Date(System.currentTimeMillis());
            System.out.println("open connection ok at " + end + ",cost:"+ (end.getTime() - current.getTime()));
            connection.setRequestProperty("Content-Type", "text/xml");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            connection.setReadTimeout(60 * 1000 * Integer.parseInt(timeOut));
            byte data[] = sendData.getBytes();
            current = new Date(System.currentTimeMillis());
            System.out.println("[SSLIX]notifyEai,begint to write data at " + current);
            OutputStream out = connection.getOutputStream();
            out.write(data);
            end = new Date(System.currentTimeMillis());
            System.out.println("write data ok at " + end + ",cost:"  + (end.getTime() - current.getTime()));
            StringBuffer receivedData = new StringBuffer();
            current = new Date(System.currentTimeMillis());
            System.out.println("begint to read data at " + current);
            InputStreamReader inReader = new InputStreamReader(connection.getInputStream(), "UTF-8");
            BufferedReader aReader = new BufferedReader(inReader);
            String aLine;
            while ((aLine = aReader.readLine()) != null) {
                receivedData.append(aLine);
            }
            end = new Date(System.currentTimeMillis());
            System.out.println("read data ok at " + end + ",cost:" + (end.getTime() - current.getTime()));
            System.out.println("开始返回状态码");
            Integer statusCode = connection.getResponseCode();
            System.out.println("返回状态码:" + statusCode);
            aReader.close();
            connection.disconnect();
            res = receivedData.toString();
            return res;
        }
    
        public static class MyAuthenticator extends Authenticator {
            private String user = "";
            private String password = "";
    
            public MyAuthenticator(String user, String password) {
                this.user = user;
                this.password = password;
            }
    
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(user, password.toCharArray());
            }
        }
        
        public static void main(String[] args) throws Exception {
            System.out.println(ClientSendDataSingle.send("https://localhost:8443/spdbSjptServer", "", "", "5", false, "D:/cert/tbb.jks", "12345678"));
        }
    }

    双向认证:

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Authenticator;
    import java.net.InetSocketAddress;
    import java.net.Proxy;
    import java.net.URL;
    import java.util.Date;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLSession;
    
    import com.pf.util.ClientSendDataSingle.MyAuthenticator;
    
    /**
     * 
     * @Description https双向认证
     * @author sprinng
     *
     */
    public class ClientSendDataDouble {
        /**
         * 
         * @param sendurl 请求地址
         * @param res  返回结果
         * @param sendData 参数
         * @param timeOut  超时时间(min)
         * @param useProxy  是否使用代理
         * @param trustStorePath 服务器证书路径
         * @param trustStorePwd 服务器证书密码
         * @param keyStore 客户端证书路径
         * @param keyStorePwd 客户端证书密码
         * @param keyStoreType 客户端证书类型      如:JKS PKCS12等
         * @return
         * @throws Exception
         */
        public static String send(String sendurl, String res, String sendData, String timeOut, boolean useProxy, String trustStorePath, String trustStorePwd, String keyStore, String keyStorePwd, String keyStoreType) throws Exception {
            //设置客户端证书
            System.setProperty("javax.net.ssl.keyStore", keyStore);
            System.setProperty("javax.net.ssl.keyStorePassword",keyStorePwd);
            System.setProperty("javax.net.ssl.keyStoreType", keyStoreType);
             
            //设置服务器证书
            System.setProperty("javax.net.ssl.trustStore", trustStorePath);
            System.setProperty("javax.net.ssl.trustStorePassword",  trustStorePwd);
            URL url = new URL(sendurl);
            HttpsURLConnection connection = null;
            HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName, SSLSession session) {
                    return true;
                }
            };
            System.setProperty("java.protocol.handler.pkgs","sun.net.www.protocol");
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
            Date current = new Date(System.currentTimeMillis());
            System.out.println("begint to open connection at " + current);
            if(useProxy){//使用代理
                InetSocketAddress isa = new InetSocketAddress(PropertiesUtil.properties.getProperty("proxy_host"), Integer.parseInt(PropertiesUtil.properties.getProperty("proxy_port")));
                Proxy proxy = new Proxy(Proxy.Type.HTTP, isa);
                Authenticator.setDefault(new MyAuthenticator(PropertiesUtil.properties.getProperty("proxy_user"), PropertiesUtil.properties.getProperty("proxy_password")));
                connection = (HttpsURLConnection) url.openConnection(proxy);
            }else{
                connection = (HttpsURLConnection) url.openConnection();
            }
            Date end = new Date(System.currentTimeMillis());
            System.out.println("open connection ok at " + end + ",cost:"+ (end.getTime() - current.getTime()));
            connection.setRequestProperty("Content-Type", "text/xml");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            connection.setReadTimeout(30000);
            byte data[] = sendData.getBytes();
            current = new Date(System.currentTimeMillis());
            System.out.println("[SSLIX]notifyEai,begint to write data at " + current);
            OutputStream out = connection.getOutputStream();
            out.write(data);
            end = new Date(System.currentTimeMillis());
            System.out.println("write data ok at " + end + ",cost:" + (end.getTime() - current.getTime()));
            StringBuffer receivedData = new StringBuffer();
            current = new Date(System.currentTimeMillis());
            System.out.println("begint to read data at " + current);
            InputStreamReader inReader = new InputStreamReader(connection.getInputStream(), "UTF-8");
            BufferedReader aReader = new BufferedReader(inReader);
            String aLine;
            while ((aLine = aReader.readLine()) != null) {
                receivedData.append(aLine);
            }
            end = new Date(System.currentTimeMillis());
            System.out.println("read data ok at " + end + ",cost:" + (end.getTime() - current.getTime()));
            System.out.println("开始返回状态码");
            Integer statusCode = connection.getResponseCode();
            System.out.println("返回状态码:" + statusCode);
            aReader.close();
            connection.disconnect();
            return receivedData.toString();
        }
    
        public static void main(String[] args) throws Exception {
            System.out.println(ClientSendDataDouble.send("https://localhost:8443/spdbSjptServer/", "", "", "5", false, "D:/cert/tbb.jks", "12345678", "D:/cert/client.p12", "12345678", "PKCS12"));
        }
    }

    附:

    import java.io.IOException;
    import java.util.Properties;
    
    
    public class PropertiesUtil {
        public static final Properties properties = new Properties();
        static {
             try {
              properties.load(PropertiesUtil.class.getClassLoader().getResourceAsStream("config.properties"));
             } catch (IOException e) { 
                 ECommonUtil.getLog().error("初始config配置文件失败");
            }
        }
    }
  • 相关阅读:
    error MSB8031(将vs2010的工程用vs2013打开时出的错)
    MFC如何使控件大小随着对话框大小自动调整
    基于MFC对话框程序中添加菜单栏 (CMenu)
    mfc改变对话框窗口大小
    MFC设置对话框大小
    uart与usart区别
    uart接口介绍和认识
    USB引脚属性
    使用百度云服务器BCC搭建网站,过程记录
    linux下文件的复制、移动与删除命令为:cp,mv,rm
  • 原文地址:https://www.cnblogs.com/sprinng/p/5757795.html
Copyright © 2011-2022 走看看