文章目录

  • 前言
  • 一、准备
    • 1.构建客户端证书
    • 2.构建服务器端证书
    • 3.tomcat准备
  • 二、单向认证
    • 1.配置
    • 2.代码访问
  • 三、双向认证
    • 1.配置
    • 2.浏览器访问
    • 3.代码访问
  • 总结

前言

本文通过构建自签名证书,实现浏览器和代码发送https请求的单向认证,双向认证和代码层绕过证书校验。


一、准备

1.构建客户端证书

keytool -genkey -v -alias clientKey -keyalg RSA -storetype PKCS12 -keystore client.key.p12

得到文件client.key.p12,密码为:123456,alias为clientKey

2.构建服务器端证书

keytool -genkey -v -alias serverKey -keyalg RSA -keystore server.keystore -validity 365
装换格式
keytool -importkeystore -srckeystore server.keystore -destkeystore server.keystore -deststoretype pkcs12

得到文件:server.keystore,密码为:123456,别名serverKey

3.tomcat准备

tomcat的webapps目录下创建ssl目录,并将index.jsp文件放到该目录下

<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="UTF-8" %>
<%@ page import="java.util.Enumeration" %><!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><title>test</title>
</head>
<body>
<p>request属性信息</p>
<pre><%for(Enumeration en = request.getAttributeNames();en.hasMoreElements();){String name = (String) en.nextElement();out.println(name);out.println(" = " + request.getAttribute(name));out.println();}%>
</pre>
</body>
</html>

ssl目录下创建WEB-INF目录,WEB-INF目录下创建web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><display-name>ssl</display-name><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>

二、单向认证

1.配置

tomcat的server.xml配置文件如下:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150" SSLEnabled="true" scheme="https" secure="true" sslProtocol="TLS" keystoreFile="conf/server.keystore" keystorePass="123456"/>

将上面生成的server.keystore文件放到server…xml的同级目录,启动服务
使用浏览器访问:https://localhost:8443/ssl/,会出现提醒,点击继续访问就可看到返回的内容

2.代码访问

客户端代码要验证服务器的证书,就是在客户端的密钥库中添加服务的的证书。我们可以通过浏览器获得服务器返回的证书,再将其导入到本地的密钥库中。

按照以上步骤得到文件server.cer,将该证书导入密钥库client.key.p12
keytool -importcert -trustcacerts -alias serverKey -file server.cer -keystore client.key.p12
可以通过查看命令
keytool -importcert -trustcacerts -alias serverKey -file server.cer -keystore client.key.p12
看到client.key.p12中有两个条目,一个类型为:PrivateKeyEntry,一个类型为:trustedCertEntry

代码测试:
获取SSLSocketFactory

public class HttpConfig {public static final String PROTOCOL = "TLS";/*** 获取keystore** @param keystorePath keystore路径* @param password     密码* @return 密钥库* @throws Exception Exception*/private static KeyStore getKeyStore(String keystorePath, String password) throws Exception {KeyStore keystore = KeyStore.getInstance("PKCS12");
//        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());try (FileInputStream in = new FileInputStream(keystorePath);) {keystore.load(in, password.toCharArray());return keystore;}}/*** 获取 SSLSocketFactory* @param keyManagerFactory 密钥库工厂* @param trustFactory 信任库工厂* @return SSLSocketFactory* @throws Exception Exception*/public static SSLSocketFactory getSSLSocketFactory(KeyManagerFactory keyManagerFactory,TrustManagerFactory trustFactory) throws Exception {// 实例化SSL上下文SSLContext context = SSLContext.getInstance(PROTOCOL);KeyManager[] keyManagers = Optional.ofNullable(keyManagerFactory).map(KeyManagerFactory::getKeyManagers).orElse(null);TrustManager[] trustManagers = Optional.ofNullable(trustFactory).map(TrustManagerFactory::getTrustManagers).orElse(null);context.init(keyManagers, trustManagers, new SecureRandom());return context.getSocketFactory();}public static TrustManagerFactory getTrustManagersFactory(String trustStorePath, String password) throws Exception {// 实例化信任库TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());KeyStore trustStore = getKeyStore(trustStorePath, password);// 初始化信任库trustFactory.init(trustStore);return trustFactory;}public static KeyManagerFactory getKeyManagerFactory(String keystorePath, String password) throws Exception {KeyManagerFactory factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());// 获取密钥库KeyStore keyStore = getKeyStore(keystorePath, password);// 初始化密钥工厂factory.init(keyStore, password.toCharArray());return factory;}
}

测试

public class HttpsRequestTest {private String password = "123456";private String trustStorePath = "D:\\ssl\\client.key.p12";//笔者这里用localhost会报一个签名不匹配问题private String httpUrl = "https://www.xuecheng.com:8443/ssl/";@Testpublic void oneWayAuthentication() throws Exception {URL url = new URL(httpUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();// 打开输入输出流conn.setDoInput(true);//域名校验conn.setHostnameVerifier((k, t) -> true);// 单向认证TrustManagerFactory trustManagersFactory =HttpConfig.getTrustManagersFactory(trustStorePath, password);SSLSocketFactory sslSocketFactory = HttpConfig.getSSLSocketFactory(null, trustManagersFactory);conn.setSSLSocketFactory(sslSocketFactory);conn.connect();receiveData(conn);conn.disconnect();}private void receiveData(HttpsURLConnection conn) throws IOException {int length = conn.getContentLength();byte[] data = null;if (length != -1) {DataInputStream input = new DataInputStream(conn.getInputStream());data = new byte[length];input.readFully(data);input.close();System.out.println(new String(data));}}
}

三、双向认证

1.配置

双向认证就是让服务器信任客户端证书的证书。就需要将客户端的证书导入到服务器中。
因不能直接将PKCS12格式的证书库导入服务器证书库,需要将客户端证书导出为一个单独的CER文件
keytool -export -alias clientKey -keystore client.key.p12 -storetype PKCS12 -file client.cer -rfc
这样就得到一个client.cer证书,该证书发给服务器的伙伴,服务器端的伙伴需要将此证书导入到服务器的密钥库中

通过命令:
keytool -list -v -keystore server.keystore
同样可以看到服务器端的密钥库中有两个条目:一个类型为trustedCertEntry,一个为 PrivateKeyEntry

配置tomcat的server.xml

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150" SSLEnabled="true" scheme="https" secure="true" sslProtocol="TLS" keystoreFile="conf/server.keystore" keystorePass="123456"keystoreType="PKCS12"truststoreFile="conf/server.keystore"truststorePass="123456"truststoreType="PKCS12"clientAuth="true"/>

2.浏览器访问

服务器启动后,访问出现以下页面

双击client.key.p12文件进行证书安装


安装成功后就可以继续访问

3.代码访问

public class HttpsRequestTest {private String password = "123456";private String trustStorePath = "D:\\ssl\\client.key.p12";private String keyStorePath = "D:\\ssl\\client.key.p12";// 服务器服务地址(注意:笔者这里用localhost会报一个签名不匹配问题)private String httpUrl = "https://www.xuecheng.com:8443/ssl/";@Testpublic void twoWayAuthentication() throws Exception {URL url = new URL(httpUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();// 打开输入输出流conn.setDoInput(true);//域名校验conn.setHostnameVerifier((k, t) -> true);// 双向认证TrustManagerFactory trustManagersFactory =HttpConfig.getTrustManagersFactory(trustStorePath, password);KeyManagerFactory keyManagerFactory = HttpConfig.getKeyManagerFactory(keyStorePath, password);SSLSocketFactory sslSocketFactory = HttpConfig.getSSLSocketFactory(keyManagerFactory, trustManagersFactory);conn.setSSLSocketFactory(sslSocketFactory);conn.connect();receiveData(conn);conn.disconnect();}private void receiveData(HttpsURLConnection conn) throws IOException {int length = conn.getContentLength();byte[] data = null;if (length != -1) {DataInputStream input = new DataInputStream(conn.getInputStream());data = new byte[length];input.readFully(data);input.close();System.out.println(new String(data));}}
}

总结

本篇代码访问方面虽然没有集成主流框架httpclient,但弄清楚了认证的流程和原理后,可以在使用httpclient发送请求时做到单向认证,双向认证和绕过证书认证。

java实现https请求单向认证、双向认证相关推荐

  1. JAVA实现发送HTTPS请求(SSL双向认证)

    一.项目背景 Java项目需要作为客户端发起HTTPS请求访问服务端,并且需要携带证书进行SSL双向认证,当前提供的证书相关文件有:ca.crt.ca.key.client.crt.client.ke ...

  2. HTTPS原理、单向和双向认证

    参考文章:https://blog.51cto.com/11883699/2160032 https://www.songma.com/news/txtlist_i39807v.html 众所周知,W ...

  3. 数字证书原理详细介绍 单向认证 双向认证

    证书:就是为了证明自己身份的东西,所以证书要提供给需要校验我们身份的人:一般情况下,客户端需要校验服务端有没有被人伪造,所以客户端需要安装对应的服务端的证书:证书的实质内容就是一把公钥 这里面主要有三 ...

  4. 锐捷路由器CHAP 单向认证 双向认证

    单向认证 R1为认证客户端 进入Router1 进入Serial 2/0接口 interface Serial 2/0 封装PPP协议 encapsulation ppp 启用CHAP认证 ppp a ...

  5. java实现https请求

    参考: https://www.cnblogs.com/chinway/p/5802541.html java 实现https请求 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易 ...

  6. 数据和安全②HTTPS单向和双向认证

    前言 示例 使用SpringBoot模拟服务端和客户端,使用okhttp作为httpClient工具. 如果对https相关理论不太熟悉和理解的可以看上一篇数据和安全①加解密理论概述 Okhttp h ...

  7. java 调用tomcat api,Tomcat采用双向认证https协议通过JavaAPI调用(一)配置SSL

    双向认证(个人理解): 客户端认证: 客户端通过浏览器访问某一网站时,如果该网站为HTTPS网站,浏览器会自动检测系统中是否存在该网站的信任证书,如果没有信任证书,浏览器一般会拒绝访问,IE会有一个继 ...

  8. HTTPS单向认证双向认证

    单向认证:保证server是真的,通道是安全的(对称密钥): 双向认证:保证client和server是真的,通道是安全的(对称密钥): 单向认证: 1.clinet<--server 2.cl ...

  9. Java加密技术(十一)——双向认证

    对于双向认证,做一个简单的描述.  服务器端下发证书,客户端接受证书.证书带有公钥信息,用于验证服务器端.对数据加密/解密,起到OSI五类服务的认证(鉴别)服务和保密性服务. 这只是单向认证,为什么? ...

  10. ios https 单项认证 双向认证 以及服务端配置

    单项认证:客户端APP包里保存一份证书 用于校验服务端证书是否合法 双向认证:单项认证以外,   客户端(不是app,这里指系统)要拥有一份证书 用于传给服务端用于校验客户端证书是否合法 分两方面讲解 ...

最新文章

  1. matlab画一个局部放大的图中图
  2. 22解析函数的级数表示(一)
  3. 查看,添加和删除GIT配置的正确姿势
  4. 《汇编语言》第一章笔记
  5. C++11 打印系统时间(精确到毫秒)和时间戳(毫秒单位)
  6. iOS 实时录音和播放
  7. 正态分布推导瑞利分布,瑞利信道的模型
  8. 传奇外网架设教程带图文解说——Gom引擎
  9. android手机usb设置在哪里,手机usb调试在哪,教您安卓手机怎么打开USB调试
  10. 解决米8应用下面有黑边的问题
  11. word计算机板书,Word板书设计怎么写
  12. 深入浅出Docker 读书笔记(九)
  13. 青岛大学计算机科学技术学院图灵班,北京大学计算机实验班(图灵班)介绍
  14. 计算机辅助培训的策略,宁波诺丁汉大学学习策略培训对解决计算机辅助语言教学环境下信息过剩问题的启示...
  15. Java压缩字符串的方法收集
  16. ubuntu安装docker详细教程以及配置阿里云镜像加速
  17. 什么是 返点、分销、直销、代理、代销
  18. 利用photoshop创建一个3D绚丽的文…
  19. html5 boilerplate 教程,HTML5 Boilerplate
  20. 全志A33学习笔记及问题汇总

热门文章

  1. 基于frp实现将安卓手机变成代理服务器
  2. 数据库优化java设计模式架构 策略 责任链
  3. 解决:本地计算机上的MySQL80服务启动后停止,某些服务在未由其他服务或者程序使用时将自动停止
  4. JUC学习之CountDownLatch入门
  5. 商品的SPU与SKU的区别
  6. 华为不同vlan单臂路由的配置
  7. redis入门(转)
  8. Installation openQRM
  9. 月薪一万的北漂可以过上什么样的生活?
  10. nginx 过滤请求URL参数及重定向