https one-way authentication and two-way authentication demo (SpringBoot+okhttp3+keytool self-signed)

table of Contents

 

I. Introduction

2. Software version

Three, one-way authentication

Four, two-way authentication


I. Introduction

HTTPS (full name: Hyper Text Transfer Protocol over SecureSocket Layer) is an HTTP channel with security as the goal. On the basis of HTTP, transmission encryption and identity authentication ensure the security of the transmission process [1]. HTTPS adds an SSL layer on the basis of HTTP. The security basis of HTTPS is SSL, so SSL is required for the details of encryption. HTTPS has a default port different from HTTP and an encryption/authentication layer (between HTTP and TCP). This system provides authentication and encrypted communication methods.

This article uses okhttp3 to access the https interface created by SpringBoot.

2. Software version

SpringBoot:2.1.2

okhttp3: 3.2.0

keytool:jdk1.8.0_77

Three, one-way authentication

1Generate server certificate

keytool -genkey -alias server -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -storepass 123456 -storetype PKCS12 -keystore C:\Users\admin\Desktop\server.p12

Remember the key store password, use it in the SpringBoot configuration

2Export the server cer certificate

keytool -export -alias server -keystore C:\Users\admin\Desktop\server.p12 -storetype PKCS12 -keypass 123456 -file C:\Users\admin\Desktop\server.cer

3 configure SpringBoot

Copy server.p12 to the resources directory of SpringBoot

#ssl配置
server.ssl.enabled=true
server.ssl.key-store=classpath:server.p12
server.ssl.key-store-password=123456
server.ssl.key-store-type=JKS
# 证书别名
server.ssl.key-alias=server

4 browser test

Visit https://localhost:8080/demo

5okhttp3 test

path: specify the path of server.cer

package com.asyf.demo.other_api.okhttp3;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

/**
 * https单向认证
 */
public class Test2 {

    //安全传输层协议
    private static final String PROTOCOL = "TLS";

    // JKS/PKCS12
    private static final String KEY_KEYSTORE_TYPE = "PKCS12";

    private static SSLSocketFactory getSocketFactory(String cerPath) throws Exception {
        SSLSocketFactory socketFactory = null;
        try (InputStream cerInputStream = new FileInputStream(new File(cerPath))) {
            TrustManager[] trustManagers = getTrustManagers(cerInputStream);
            SSLContext sslContext = getSslContext(trustManagers);
            socketFactory = sslContext.getSocketFactory();
        }
        return socketFactory;
    }

    private static SSLContext getSslContext(TrustManager[] trustManagers) throws Exception {
        SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
        sslContext.init(null, trustManagers, new SecureRandom());
        return sslContext;
    }

    private static TrustManager[] getTrustManagers(InputStream inputStream) throws Exception {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyStore keyStore = KeyStore.getInstance(KEY_KEYSTORE_TYPE);
        //加载证书
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Certificate ca = certificateFactory.generateCertificate(inputStream);
        keyStore.load(null, null);
        //设置公钥
        keyStore.setCertificateEntry("server", ca);
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        return trustManagers;
    }

    public static void main(String[] args) throws Exception {
        //获取SSLSocketFactory
        String certPath = "D:\\workspace\\asyf_demo\\demo\\src\\main\\java\\com\\asyf\\demo\\other_api\\okhttp3\\server.cer";//服务端公钥
        SSLSocketFactory socketFactory = getSocketFactory(certPath);
        //发送请求
        String url = "https://127.0.0.1:8080/demo";
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        clientBuilder.sslSocketFactory(socketFactory);
        //解决报错javax.net.ssl.SSLPeerUnverifiedException: Hostname 127.0.0.1 not verified
        clientBuilder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                System.out.println("主机:" + s);
                return true;
            }
        });
        OkHttpClient client = clientBuilder.build();

        Request.Builder builder = new Request.Builder().url(url);
        Request request = builder.build();

        Response response = client.newCall(request).execute();
        String result = response.body().string();
        //打印请求结果
        System.out.println(result);
    }

}

 Console:

Four, two-way authentication

1Generate client certificate

keytool -genkey -alias client -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -storepass 123456 -storetype PKCS12 -keystore C:\Users\admin\Desktop\client.p12

2Export the client cer certificate

keytool -export -alias client -keystore C:\Users\admin\Desktop\client.p12 -storetype PKCS12 -keypass 123456 -file C:\Users\admin\Desktop\client.cer

3 Generate the keystore to store the certificate trusted by springboot

keytool -genkey -alias springboot_keystore -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -storepass 123456 -storetype PKCS12 -keystore C:\Users\admin\Desktop\springboot_keystore.keystore

4Import the client's public key to springboot_keystore.keystore

keytool -import -v -file C:\Users\admin\Desktop\client.cer -keystore C:\Users\admin\Desktop\springboot_keystore.keystore -storepass 123456

5 configure SpringBoot

Copy springboot_keystore.keystore to the SpringBoot project and add the following configuration

#双向认证配置
server.ssl.trust-store=classpath:springboot_keystore.keystore
server.ssl.trust-store-password=123456
server.ssl.client-auth=need
server.ssl.trust-store-type=JKS
server.ssl.trust-store-provider=SUN

6 browser test

Direct access will cause the following error

Need to install the certificate in the computer

Double-click client.p12, install the certificate (demo is win10 environment)

After the installation is successful, refresh the browser and prompt to select the certificate. Click "OK".

Then visit the https interface and see the result as shown in the figure below, indicating that the configuration is successful.

7okhttp3 test

path: Specify the path of client.p12

If you continue to access the main function with one-way authentication, the console will print an exception message:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

Test code:

package com.asyf.demo.other_api.okhttp3;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

/**
 * https双向认证
 */
public class Test {

    //安全传输层协议
    private static final String PROTOCOL = "TLS";

    // JKS/PKCS12
    private static final String KEY_KEYSTORE_TYPE = "PKCS12";

    public static SSLSocketFactory getSocketFactory(String cerPath, String p12Path, String password) throws Exception {
        InputStream cerInputStream = null;
        InputStream p12InputStream = null;
        SSLSocketFactory socketFactory = null;
        try {
            cerInputStream = new FileInputStream(new File(cerPath));
            p12InputStream = new FileInputStream(new File(p12Path));
            KeyManager[] keyManagers = getKeyManagers(p12InputStream, password);
            TrustManager[] trustManagers = getTrustManagers(cerInputStream);
            SSLContext sslContext = getSslContext(keyManagers, trustManagers);
            socketFactory = sslContext.getSocketFactory();
        } finally {
            if (cerInputStream != null) {
                cerInputStream.close();
            }
            if (p12InputStream != null) {
                p12InputStream.close();
            }
        }
        return socketFactory;
    }

    private static SSLContext getSslContext(KeyManager[] keyManagers, TrustManager[] trustManagers) throws Exception {
        SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
        sslContext.init(keyManagers, trustManagers, new SecureRandom());
        return sslContext;
    }

    private static KeyManager[] getKeyManagers(InputStream inputStream, String password) throws Exception {
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        KeyStore keyStore = KeyStore.getInstance(KEY_KEYSTORE_TYPE);
        //加载证书
        keyStore.load(inputStream, password.toCharArray());
        keyManagerFactory.init(keyStore, password.toCharArray());
        KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
        return keyManagers;
    }

    private static TrustManager[] getTrustManagers(InputStream inputStream) throws Exception {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyStore keyStore = KeyStore.getInstance(KEY_KEYSTORE_TYPE);
        //加载证书
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Certificate ca = certificateFactory.generateCertificate(inputStream);
        keyStore.load(null, null);
        //设置公钥
        keyStore.setCertificateEntry("server", ca);
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        return trustManagers;
    }

    public static void main(String[] args) throws Exception {
        //获取SSLSocketFactory
        String certPath = "D:\\workspace\\asyf_demo\\demo\\src\\main\\java\\com\\asyf\\demo\\other_api\\okhttp3\\server.cer";//服务端公钥
        String p12Path = "D:\\workspace\\asyf_demo\\demo\\src\\main\\java\\com\\asyf\\demo\\other_api\\okhttp3\\client.p12";//客户端私钥
        SSLSocketFactory socketFactory = getSocketFactory(certPath, p12Path, "123456");
        //发送请求
        String url = "https://127.0.0.1:8080/demo";
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        clientBuilder.sslSocketFactory(socketFactory);
        //解决报错javax.net.ssl.SSLPeerUnverifiedException: Hostname 127.0.0.1 not verified
        clientBuilder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                System.out.println("主机:" + s);
                return true;
            }
        });
        OkHttpClient client = clientBuilder.build();

        Request.Builder builder = new Request.Builder().url(url);
        Request request = builder.build();

        Response response = client.newCall(request).execute();
        String result = response.body().string();
        //打印结果返回数据
        System.out.println(result);
    }

}

Console:

Guess you like

Origin blog.csdn.net/cs373616511/article/details/105628692