Websocket是基于Http的一种长连接方案,一些简单的IM产品会基于Websocket实现 但是如果聊天的内容比较敏感,比如在Websocket通道中聊天内容如果涉及到卡密、金钱等信息,那一定要对Websocket的传输进行保护。
https或者wss是最基本的防嗅探和传输加密方式,这里演示下如何配置wss的多种方式;
本文知识点:
- p12格式文件与证书文件介绍
- 如何生成p12文件和证书文件,以及如何互相转换
- Nginx如何配置Https
- Spring Boot如何配置Https?
- WSS如何配置和使用?
过程
证书和p12基本概念
证书一般包含两个文件:
- 证书文件,可以理解为公钥,用户访问的时候发给用户的
- 私钥文件,在数据传输过程中对公钥加密的内容进行解密
p12为是保存私钥和证书的组合格式,同时包含了公钥和私钥内容。p12文件和证书可以互相转换。
转换方式如下:
# 私钥和证书生成p12文件
openssl pkcs12 -inkey PRIVATE_TEST.key -in PUBLIC_TEST.pem -export -out TEST.p12
# p12文件生成证书和私钥
openssl pkcs12 -nokeys -in TEST.p12 -out PUBLIC_TEST.pem
openssl pkcs12 -nocerts -nodes -in TEST.p12 -out PRIVATE_TEST.key
生成证书和p12文件
如果想要使用wss,首先要有个证书才行,证书有两种来源:
- CA机构颁发,当然目前各种云产品都会帮我们做掉这个事情,阿里云上如果有购买域名,可以申请免费的证书
- 自己签名证书,使用OpenSSL,keytools,或者Mac的钥匙串;
阿里云
在阿里云的菜单下面,安全部分,有个SSL证书
因为阿里云的证书要收费,我们考虑一些便宜又简单的方案
openssl
如果在Nginx中使用:
直接生成公钥和私钥:
openssl req -newkey rsa:2048 -sha256 -nodes -keyout PRIVATE_TEST.key -x509 -days 365 -out PUBLIC_TEST.pem -subj "/C=NG/ST=Lagos/L=Lagos/O=YOUR_ORG_NAME_HERE/CN=test.aihe.space"
将公钥和私钥转为P12格式
openssl pkcs12 -inkey PRIVATE_TEST.key -in PUBLIC_TEST.pem -export -out TEST.p12
keytool
# 生成一个jks格式的证书文件,
keytool -genkeypair -alias tomcat -keyalg RSA -keystore wss.jks
# 将JKS的文件,转换为p12格式的文件;
keytool -importkeystore -srckeystore wss.jks -destkeystore wss.p12 -deststoretype pkcs12
# 从P12的文件中提取证书和提取私钥
openssl pkcs12 -nokeys -in wss.p12 -out wss.pem
openssl pkcs12 -nocerts -nodes -in wss.p12 -out wss.private.key
如果要在Nginx中使用,方式一样:
ssl_certificate "cert/wss.pem";
ssl_certificate_key "cert/wss.private.key";
Mac钥匙串
导出为P12格式之后仍然按照老方式:
openssl pkcs12 -nokeys -in aihetest0916.p12 -out aihetest.pem
openssl pkcs12 -nocerts -nodes -in aihetest0916.p12 -out aihetest.key
Nginx配置Https-公私钥方式
在nginx下添加如下内容:在nginx.conf文件中,或者nginx配置目录下conf.d种新建一个文件都可以。
server {
listen 443 ssl ;
listen [::]:443 ssl ;
server_name ssl.aihe.space;
root /usr/share/nginx/html;
ssl_certificate "cert/wss.pem";
ssl_certificate_key "cert/wss.private.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
#ssl_ciphers PROFILE=SYSTEM;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_verify_client off;
location / {
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# 这里配置了反向代理服务器的地址
proxy_pass http://127.0.0.1:8080;
}
}
在Safari浏览器上可以看到证书信息,网站访问也是生效的,谷歌浏览器如果遇到自签名证书不让访问,相对麻烦,所以还是用Safari浏览器。
SpringBoot配置Https-使用P12文件
1、将生成好的P12文件拷贝到resource目录下; 2、配置application.properties文件
#server.port=443
server.ssl.key-store=classpath:aihetest0916.p12
server.ssl.key-store-password=123456
server.ssl.key-password=123456
server.ssl.key-alias=aihetest0916
3、启动查看效果;
WSS配置和使用
Wss是基于Https的,如果已经配置好了Https:
- 在Nginx中反向代理https到后端的http服务器即可,http服务器有Websocket。
- 直连SpringBoot的WSS应用,让SpringBoot配置支持HTTPS
在Spring Boot中的Websocket代码:
@Configuration
@Slf4j
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
List<HandshakeInterceptor> handshakeInterceptorList;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new DemoTextWebSocketHandler(), "/websocket-spring").setAllowedOrigins("*")
;
}
private static class DemoTextWebSocketHandler extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
log.info("建立连接 {}", session.getId());
super.afterConnectionEstablished(session);
TextMessage textMessage = new TextMessage("建立连接:" + session.getId());
session.sendMessage(textMessage);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
log.info("处理收到的数据:{}", new String(message.asBytes()));
session.sendMessage(new TextMessage("收到:" + new String(message.asBytes())));
}
}
}
测试本地访问:
测试Nginx反向代理
总结
- 现在证书配置有两种常见文件,p12文件和公钥私钥方式,p12只是把公钥和私钥组合了一下,p12和公钥私钥可以互相转换。
- Nginx配置Https使用公钥和私钥的方式
- SpringBoot应用中可以直接使用p12文件格式配置Https
- WSS加密其实只需要把Https功能配置好就行;在nginx反向代理中需要nginx支持下websocket的功能,在spring boot中默认就支持;
- 演示了几种生成证书的方式:阿里云、openssl、keytool、以及Mac电脑的钥匙串也可以创建对应的证书文件。