eclipse中使用Jetty插件实现https请求与SSL双向验证

链接

完整程序源码下载,csdn还没验证通过
1. 包含https和socket两种ssl测试代码
2. 所有密码均为123456

环境准备

  • eclipse中安装run-jetty-run插件 csdn下载资源
  • java环境支持,需要使用keytool命令

开始

生成服务器证书

  1. keytool -genkey -alias serverkey -keyalg RSA -keystore kserver.keystore
  2. keytool -export -alias serverkey -keystore kserver.keystore -rfc -file server.crt
  3. keytool -import -alias serverkey -file server.crt -keystore tclient.keystore

这里写图片描述
其中:kserver.keystore就是服务使用的keystore,server.crt是证书,tclient.keystore是给客户端使用的信任keystore

特别说明:这里我们使用自己的keystore直接导出证书,仅在自己的内部系统可用,如果希望在公网可用,应生成crs向ca申请证书

生成客户端证书

JKS方式

  1. keytool -genkey -alias clientKey -keystore kclient.keystore
  2. keytool -export -alias clientKey -keystore kclient.keystore -file client.crt
  3. keytool -import -alias clientKey -file client.crt -keystore tserver.keystore

PKCS12方式

  1. keytool -genkeypair -alias clientkey -keyalg RSA -storetype PKCS12 -keystore client.p12
  2. keytool -export -alias clientKey -keystore client.p12 -storetype PKCS12 -rfc -file client.crt
  3. keytool -import -alias clientKey -file client.crt -keystore tserver.keystore

配置Jetty环境

这里写图片描述

特别说明:这里单独配置了jetty.xml文件,因为无法确认jetty在做双向验证时候的可信证书从哪里找的,所以通过jetty.xml文件来指定位置。如果使用单向验证,那么可以直接使用jetty的ssl配置即可。

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">

<Configure id="Server" class="org.eclipse.jetty.server.Server">
    <Call name="addConnector">
     <Arg>
       <New class="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
         <Arg>
           <New class="org.eclipse.jetty.http.ssl.SslContextFactory">
             <Set name="keyStore">D:/workspace/SSLServer/src/ssl/keystore/server/kserver.keystore</Set>
             <Set name="keyStorePassword">123456</Set>
             <Set name="keyManagerPassword">123456</Set>
             <!-- JSK -->
             <Set name="trustStore">D:/workspace/SSLServer/src/ssl/keystore/client/tserver.keystore</Set>
             <!-- PKCS12 -->
             <!--<Set name="trustStore">D:/workspace/SSLServer/src/ssl/keystore/pk12/tserver.keystore</Set>-->
             <Set name="trustStorePassword">123456</Set>
             <Set name="needClientAuth">true</Set>
           </New>
         </Arg>
         <Set name="port">8443</Set>
         <Set name="maxIdleTime">30000</Set>
       </New>
     </Arg>
   </Call>
</Configure>

客户端请求代码

package ssl.https;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.SecureRandom;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class SSLSayClient {

    private static final String CLIENT_KEY_STORE_PASSWORD = "123456";
    private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456";

    private SSLSocketFactory ssLSocketFactory;

    public static void main(String[] args) throws Exception {
        String path = "https://192.168.1.83:8443/SSLServer/say";
        SSLSayClient client = new SSLSayClient();
        client.init();// 双向验证
        // client.initOneWay();// 单向验证
        client.doPost(path);
    }

    static {
        // 默认ip地址校验通过
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
    }

    /**
     * 双向验证
     */
    public void init() {
        try {
            SSLContext ctx = SSLContext.getInstance("SSL");

            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

            KeyStore ks = KeyStore.getInstance("JKS");// JKS
            // KeyStore ks = KeyStore.getInstance("PKCS12");// PKCS12
            KeyStore tks = KeyStore.getInstance("JKS");

            // JSK
            ks.load(new FileInputStream("D:/workspace/SSLServer/src/ssl/keystore/client/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());
            // PKCS12
            // ks.load(new
            // FileInputStream("D:/workspace/SSLServer/src/ssl/keystore/pk12/client.p12"),
            // CLIENT_KEY_STORE_PASSWORD.toCharArray());
            tks.load(new FileInputStream("D:/workspace/SSLServer/src/ssl/keystore/server/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());

            kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());
            tmf.init(tks);

            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

            ssLSocketFactory = ctx.getSocketFactory();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    /**
     * 单向验证
     */
    public void initOneWay() {
        try {
            SSLContext ctx = SSLContext.getInstance("SSL");

            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

            KeyStore tks = KeyStore.getInstance("JKS");

            tks.load(new FileInputStream("D:/workspace/SSLServer/src/ssl/keystore/server/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());

            tmf.init(tks);

            ctx.init(null, tmf.getTrustManagers(), new SecureRandom());

            ssLSocketFactory = ctx.getSocketFactory();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    /**
     * POST
     */
    public void doPost(String path) throws Exception {
        if (ssLSocketFactory == null) {
            System.out.println("ERROR");
            return;
        }
        // 创建URL对象
        URL myURL = new URL(path);
        // 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
        HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
        httpsConn.setSSLSocketFactory(ssLSocketFactory);

        String encoding = "UTF-8";
        byte[] data = "Hello Server".getBytes(encoding);

        httpsConn.setRequestMethod("POST");
        httpsConn.setDoOutput(true);
        httpsConn.setRequestProperty("Content-Type", "application/json; charset=" + encoding);
        httpsConn.setRequestProperty("Content-Length", String.valueOf(data.length));
        OutputStream outStream = httpsConn.getOutputStream();
        outStream.write(data);
        outStream.flush();
        outStream.close();
        BufferedReader a = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(), "UTF-8"));
        String line = null;
        while ((line = a.readLine()) != null) {
            System.out.println(line);
        }
    }
}

服务端代码

package ssl.https;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Say extends HttpServlet {

    private static final long serialVersionUID = -840442603737824400L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Server Get");
        String encoding = "UTF-8";
        response.setContentType("application/json; charset=" + encoding);
        OutputStream outStream = response.getOutputStream();
        outStream.write("Hello Client Get".getBytes(encoding));
        outStream.flush();
        outStream.close();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Server Post");
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }

        String encoding = "UTF-8";
        response.setContentType("application/json; charset=" + encoding);
        OutputStream outStream = response.getOutputStream();
        outStream.write("Hello Client Post".getBytes(encoding));

        outStream.flush();
        outStream.close();
    }
}

验证

启动jetty服务器

提示以下信息,证明服务器启动正常

2016-02-23 10:38:52.628:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/SSLServer,[file:/D:/workspace/SSLServer/WebContent/]}
2016-02-23 10:38:52.710:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8088
2016-02-23 10:38:52.896:INFO:oejus.SslContextFactory:Enabled Protocols [SSLv2Hello, SSLv3, TLSv1] of [SSLv2Hello, SSLv3, TLSv1]
2016-02-23 10:38:52.899:INFO:oejs.AbstractConnector:Started SslSelectChannelConnector@0.0.0.0:8443

执行客户端ssl双向请求

如果请求成功,将出现如下信息:
客户端提示:
Hello Client Post
服务端提示:
Server Post
Hello Server

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潘少博

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值