# SSLDemo
Tomcat搭建SSL双向认证Demo、Java原生类库SSLSocket编程、Apache的Httpclient库模拟请求
# 证书准备
见之前[keytool命令](http://note.youdao.com/noteshare?id=3c769cd3ed0547004a87e31acb67d00c)中的**keytool生成双向认证证书**章节
测试证书库:/TestSSL/WebContent/keystore
# Tomcat配置
在${catalina.base}/conf/server.xml找到
```
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
```
取消注释,并修改成如下:
```
<Connector
SSLEnabled="true"
clientAuth="true"
keystoreFile="e:\cer\server.keystore"
keystorePass="121314"
maxThreads="150"
port="8443"
protocol="HTTP/1.1"
scheme="https"
secure="true"
sslProtocol="SSL"
truststoreFile="e:\cer\server.truststore"
truststorePass="121314"
/>
```
# 服务端项目
1. 项目结构
![](https://www.writebug.com/myres/static/uploads/2022/2/19/c5ffaf3f426e47d51e790f7114ee2b13.writebug)
2. 关键代码
/TestSSL/WebContent/WEB-INF/web.xml
该演示项目强制使用了SSL,即普通的HTTP请求也会强制重定向为HTTPS请求,配置在最下面,可以去除,这样HTTP和HTTPS都可以访问。
```java
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<servlet>
<servlet-name>SSLServlet</servlet-name>
<servlet-class>com.ssl.servlet.SSLServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SSLServlet</servlet-name>
<url-pattern>/sslServlet</url-pattern>
</servlet-mapping>
<!-- 强制SSL配置,即普通的请求也会重定向为SSL请求 -->
<security-constraint>
<web-resource-collection>
<web-resource-name>TestSSL</web-resource-name>
<url-pattern>/*</url-pattern> <!-- 全站使用SSL -->
</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>
</web-app>
```
---
/TestSSL/src/com/ssl/servlet/SSLServlet.java
```java
package com.ssl.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.cert.X509Certificate;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SSLServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String ATTR_CER = "javax.servlet.request.X509Certificate";
private static final String CONTENT_TYPE = "text/plain;charset=UTF-8";
private static final String DEFAULT_ENCODING = "UTF-8";
private static final String SCHEME_HTTPS = "https";
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
response.setCharacterEncoding(DEFAULT_ENCODING);
PrintWriter out = response.getWriter();
out.println("cmd=["+request.getParameter("cmd")+"], data=["+request.getParameter("data")+"]");
X509Certificate[] certs = (X509Certificate[]) request.getAttribute(ATTR_CER);
if (certs != null) {
int count = certs.length;
out.println("共检测到[" + count + "]个客户端证书");
for (int i = 0; i < count; i++) {
out.println("客户端证书 [" + (++i) + "]: ");
out.println("校验结果:" + verifyCertificate(certs[--i]));
out.println("证书详细:\r" + certs[i].toString());
}
} else {
if (SCHEME_HTTPS.equalsIgnoreCase(request.getScheme())) {
out.println("这是一个HTTPS请求,但是没有可用的客户端证书");
} else {
out.println("这不是一个HTTPS请求,因此无法获得客户端证书列表 ");
}
}
out.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
private boolean verifyCertificate(X509Certificate certificate) {
boolean valid = false;
try {
certificate.checkValidity();
valid=true;
} catch (Exception e) {
e.printStackTrace();
}
return valid;
}
}
```
---
/TestSSL/WebContent/index.jsp
```java
<%@ page language="java" pageEncoding="UTF-8"%>
<!doctype html>
<html lang="zh-cn">
<head>
<title>客户端证书上传</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<form action="sslServlet" method="post">
<input type="submit" value="提交证书"/>
</form>
</body>
</html>
```
---
# 浏览器演示
发布演示项目,通过浏览器访问: https://127.0.0.1:8443/TestSSL ,提示无法访问,需要导入客户端SSL证书:
双击“client.p12”或在浏览器的工具,输入生成密钥时的客户端密码“134679”,证书存储在“受信任的根证书颁发机构”,刷新浏览器即可正常访问了。
![](https://www.writebug.com/myres/static/uploads/2022/2/19/61a4320c07fbd570b3dddad76df9362f.writebug)
![](https://www.writebug.com/myres/static/uploads/2022/2/19/1392ade57ea6cd8c70f73f373630e14b.writebug)
![](https://www.writebug.com/myres/static/uploads/2022/2/19/e68c2abaee71de4da397ce1b861bf8fa.writebug)
# java原生类库SSLSocket编程
/TestSSL/src/com/ssl/SSLSocket/SSLServer.java
```java
package com.ssl.SSLSocket;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.TrustManagerFactory;
/**
* java原生包使用SSLServerSocket实现SSL通信服务器端
*
*/
public class SSLServer {
private SSLServerSocket sslServerSocket;
public static void main(String[] args) throws Exception {
SSLServer server = new SSLServer();
server.init();
System.out.println("SSLServer initialized.");
server.process();
}
//初始化
public void init() throws Exception {
int port = 1234;
String keystorePath = "E:\\cer\\server.keystore";
String trustKeystorePath = "E:\\cer\\server.truststore";
String keystorePassword = "121314";
String truststorePassword = "121314";
//这个类是原生包中的SSL连接的上下文类
SSLContext context = SSLContext.getInstance("SSL");
//服务器端证书库
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream keystoreFis = new FileInputStream(keystorePath);
keystore.load(keystoreFis, keystorePassword.toCharArray());
//信任证书库
KeyStore trustKeystore = KeyStore.getInstance("jks");
FileInputStream trustKeystoreFis = new FileInputStream(trustKeystorePath);
trustKeystore.load(trustKeystoreFis, truststorePassword.toCharArray());
//密钥库
KeyManagerFactory
基于Tomcat搭建SSL双向认证示例【100012422】
版权申诉
5星 · 超过95%的资源 170 浏览量
2023-05-24
15:14:43
上传
评论
收藏 877KB ZIP 举报
神仙别闹
- 粉丝: 2672
- 资源: 7640
最新资源
- MyBatis 动态 SQL:灵活而强大的查询构建器.pdf
- com.accordion.prettyo.apk
- 毕业设计:基于SSM的mysql-ssm软件bug管理系统(源码 + 数据库 + 说明文档)
- MTSQL8.0.35windows(64bit)-mysql-installer-community-8.0.35.0
- 人工智能引领音乐创作新时代之Suno AI
- Public-bicycle-usage-forecast-master.zip
- 通道处理过程模拟:从理论到实践.pdf
- 数据库第七次作业E-R图第一题
- 大厂面试真题Java语法基础面试专题及答案
- IMG20240428211124.jpg
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈