Java实现HTTPS请求及证书证书验证(附源码)

Java实现HTTPS请求及证书证书验证(附源码)

欢迎大家访问我的GitHub博客

https://lunan0320.github.io/

 

先发布一个初始的版本,主要以代码为主,具体的细节将之后更新。

 

服务器流程环节:

1、在本机服务器上生成一个自定义证书,格式为jks格式。
2、将自定义证书添加到客户端的信任的根证书库中,Windows系统中可以直接win+R 输入mmc即可找到添加区域。(一定是添加到信任的根证书中)
3、服务器初始化创建SSLContext上下文类型,这个过程包括创建密钥管理库和信任库两部分,使用的是SUN509的套件。
4、创建一个SSLContext的对象,初始化时使用TLSv1协议。创建两个密钥管理库和信任库的实例,作为初始化SSLContext的参数。
5、ServerFactory创建一个SSLServerSocket
6、开始接受客户端发来的请求, sslServerSocket.accept()
      1)如果没有请求就阻塞掉;
      2)如果接收到请求就创建一个线程去处理它

 
一、服务器实现代码如下:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.KeyStore;
 
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
 
public class HTTPSServer {
    private int port = 446;
    private boolean isServerDone = false;
     
    public static void main(String[] args){
        HTTPSServer server = new HTTPSServer();
        server.run();
    }
     
    HTTPSServer(){      
    }
     
    HTTPSServer(int port){
        this.port = port;
    }
     
    // 创建并初始化 SSLContext
    private SSLContext createSSLContext(){
        try{
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream("Server.jks"),"passwd".toCharArray());
             
            //创建密钥管理器
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, "passwd".toCharArray());
            KeyManager[] km = keyManagerFactory.getKeyManagers();
             
            // 创建信任库
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(keyStore);
            TrustManager[] tm = trustManagerFactory.getTrustManagers();
             
            //初始化 SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(km,  tm, null);
             
            return sslContext;
        } catch (Exception ex){
            ex.printStackTrace();
        }
         
        return null;
    }
     
    // 开启服务器
    public void run(){
        SSLContext sslContext = this.createSSLContext();
         
        try{
            // 创建服务器的 socket factory
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
             
            // 创建一个服务器Socket
            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(this.port);
             
            System.out.println("SSL服务器已开启~");
            while(!isServerDone){
                SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
                 
                // Start the server thread
                new ServerThread(sslSocket).start();
            }
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
     
    // 处理从客户端来的Socket请求
    static class ServerThread extends Thread {
        private SSLSocket sslSocket = null;
         
        ServerThread(SSLSocket sslSocket){
            this.sslSocket = sslSocket;
        }
         
        public void run(){
            sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
             
            try{
                // Start handshake
                sslSocket.startHandshake();
                 
                // 输出一些Session信息
                SSLSession sslSession = sslSocket.getSession();
                 
                System.out.println("SSLSession :");
                System.out.println("\tProtocol : "+sslSession.getProtocol());
                System.out.println("\tCipher suite : "+sslSession.getCipherSuite());
                 
                // 定义输入输出流
                InputStream inputStream = sslSocket.getInputStream();
                OutputStream outputStream = sslSocket.getOutputStream();
                 
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream));
                 
                String line = null;
                while((line = bufferedReader.readLine()) != null){
                    System.out.println("Inut : "+line);
                     
                    if(line.trim().isEmpty()){
                        break;
                    }
                }
                 
             
                printWriter.print("This is server");
                printWriter.flush();
                 
                sslSocket.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

 

 

客户端流程环节:

1、在客户都添加服务器自定义证书,格式为jks格式。
2、客户端初始化创建SSLContext上下文类型,这个过程包括创建密钥管理库和信任库两部分,使用的是SUN509的套件。
3、创建一个SSLContext的对象,初始化时使用TLSv1协议。创建两个密钥管理库和信任库的实例,作为初始化SSLContext的参数。
4、通过SocketFactory创建一个SSLSocket,IP地址和port均为服务器的。
5、证书验证

sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
交换密钥套件的过程。

在这个过程中客户端会将服务器发来的证书与本地的证书去验证
如果是保存在本地的服务器证书,则验证通过,否则证书验证不通过。
6、握手过程

sslSocket.startHandshake();

可以设置个断点进去看看,或者抓包分析一下,包括了TCP三次握手的过程。

7、连接建立完成后,即可安全交互。
 
 
二、客户端代码如下

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.KeyStore;
 
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
 
public class HTTPSClient {
    private String host = "192.168.**.**";
    private int port = 446;
     
    public static void main(String[] args){
        HTTPSClient client = new HTTPSClient();
        client.run();
    }
     
    HTTPSClient(){      
    }
     
    HTTPSClient(String host, int port){
        this.host = host;
        this.port = port;
    }
     
    // 创建并初始化 SSLContext
    private SSLContext createSSLContext(){
        try{
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream("Server.jks"),"passwd".toCharArray());
             
            // 创建一个密钥管理器
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, "passphrase".toCharArray());
            KeyManager[] km = keyManagerFactory.getKeyManagers();
             
            //创建一个信任库
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(keyStore);
            TrustManager[] tm = trustManagerFactory.getTrustManagers();
             
            // 初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(km,  tm, null);
             
            return sslContext;
        } catch (Exception ex){
            ex.printStackTrace();
        }
         
        return null;
    }
     
    // 开启客户端程序
    public void run(){
        SSLContext sslContext = this.createSSLContext();
         
        try{
            //创建Socket factory
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
             
            // 创建一个客户端的SSLsocket
            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(this.host, this.port);
             
            System.out.println("SSL 客户端开启");
            new ClientThread(sslSocket).start();
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
     
    // Thread handling the socket to server
    static class ClientThread extends Thread {
        private SSLSocket sslSocket = null;
         
        ClientThread(SSLSocket sslSocket){
            this.sslSocket = sslSocket;
        }
         
        public void run(){
            sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
             
            try{
                // 握手过程
                sslSocket.startHandshake();
                 
                // 输出关于Session的信息
                SSLSession sslSession = sslSocket.getSession();
                 
                System.out.println("SSLSession :");
                System.out.println("\tProtocol : "+sslSession.getProtocol());
                System.out.println("\tCipher suite : "+sslSession.getCipherSuite());
                 
                // Start handling application content
                InputStream inputStream = sslSocket.getInputStream();
                OutputStream outputStream = sslSocket.getOutputStream();
                 
                 //定义输入以及输出缓冲区
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream));
                 
                printWriter.println("This is client");
                printWriter.println();
                printWriter.flush();
                 
                String line = null;
                while((line = bufferedReader.readLine()) != null){
                    if(line.trim().equals("This is Client~")){
                        break;
                    }
                }
                 
                sslSocket.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
  • 4
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
单点登录(SSO)是一种身份验证和授权技术,允许用户通过一次登录即可访问多个应用程序。Java SSO单点登录的实现方式有多种,下面简要介绍一种常见的实现方式以及相关源码。 1. 实现方式:使用Token验证机制 - 用户在第一个应用程序登录后,该应用程序生成一个Token(令牌),并将Token存储在Cookie中或通过URL传递给用户的浏览器。 - 用户访问其他应用程序时,该应用程序通过Cookie或URL来获取Token。 - 应用程序使用Token来验证用户的身份,并根据需要进行授权。 2. 实现步骤: - 创建一个包含登录页面和处理登录请求的应用程序,该应用程序将生成Token并将其存储在Cookie中。 - 创建其他应用程序,这些应用程序将接收Token,并使用Token验证用户身份。 - 使用共享的数据库或其他存储方式来共享Token和用户信息。 3. 源码示例: - 在登录应用程序中,可以使用Java框架如Spring Boot或Java Servlet来处理登录请求和生成Token。相关源码可通过以下步骤实现: - 创建一个登录页面,用户输入用户名和密码。 - 在后端代码中,验证用户的凭证是否正确。 - 如果凭证正确,生成一个Token,并将其存储在Cookie中。 - 回复一个成功的登录响应给前端。 - 在其他应用程序中,可以使用Java框架如Spring Boot或Java Servlet来验证Token。相关源码示例如下: - 获取用户发送的请求,并从Cookie或URL中获取Token。 - 由于Token是被其他应用程序生成和验证的,因此需要通过网络请求或API调用将Token发送给该应用程序验证。 - 在后端代码中,验证Token的有效性,并根据需要进行授权。 - 回复一个成功或失败的响应给前端。 总之,Java SSO单点登录的实现需要使用Token验证机制,并通过Cookie或URL传递Token。在实际开发中,可以使用Java框架如Spring Boot、Java Servlet等来实现该功能。以上是一个简单的示例,实际实现可能会有所不同,但大体思路相似。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值