部署单页应用 SPA 时,我们通常使用 Nginx 做中间层进行转发代理。为了保护 Web 安全,要求我们使用 HTTPS(HTTP + SSL) 以及 WSS(Websocket + SSL) 进行通信。HTTPS 及 WSS 协议旨在保护用户数据在网络上不被窃听(机密性) 和不被篡改(完整性)。
HTTP 与 HTTPS 区别
- HTTPS 协议需要到 CA 申请证书,一般免费证书较少,因而需要一定费用;
- HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输;
- HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者默认是80,后者默认是443;
- HTTP 的连接很简单,是无状态的;HTTPS 协议是由 SSL + HTTP 协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
第一步、Nginx 配置https及wss
SSL证书
进入腾讯云服务器 - 搜索SSL证书 - 证书管理- 申请免费的SSL证书
审核通过将证书下载到本地解压,解压结果获得5个文件,如下图:
通过Nginx配置证书,我们只需Nginx文件下的证书文件和私钥文件传到服务器, 并放到Nginx的配置文件路径
- 1_www.sitven.cn_bundle.crt 证书文件
- 2_www.sitven.cn.key 私钥文件(注意:如果在申请或者购买ssl证书设置了秘钥,则该文件不存在,配置使用之前设置的密码即可)
配置文件路径:/usr/local/nginx/conf (此处为默认安装目录,请根据实际情况操作)
配置NGINX
编辑 Nginx 根目录下的配置文件nginx.conf 文件。修改内容如下:
注:此操作可通过执行 vim /usr/local/nginx/conf/nginx.conf 命令行编辑该文件。由于版本问题,配置文件可能存在不同的写法
例如:Nginx 版本为 nginx/1.15.0 以上请使用 listen 443 ssl 代替 listen 443 和 ssl on
server {
#SSL 访问端口号为 443
listen 443 ssl;
#填写绑定证书的域名
server_name www.sitven.cn;
#证书文件名称
ssl_certificate 1_www.sitven.cn_bundle.crt;
#私钥文件名称
ssl_certificate_key 2_www.sitven.cn.key;
ssl_session_timeout 5m;
#请按照以下协议配置
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
# 网站主页路径, 此为我博客项目。此路径仅供参考,具体按照实际需求操作
uwsgi_pass 127.0.0.1:8001;
include /etc/nginx/uwsgi_params;
}
}
配置完成,可通过执行以下命令验证配置文件问题
sudo nginx -t
若存在问题,请您重新配置或者根据提示修改存在问题
比如证书和私钥文件没放到正确的路径, Nginx就会提示没有这样的文件,如下图:
我们根据错误提示将证书与私钥放到正确的路径后重新进行验证
若配置不存在问题,如下图:
我们重启 Nginx,即可使用 李文君的个人博客进行访问
HTTP重定向HTTPS
http协议通过80端口通讯的而https协议通过443端口通讯, 所以我们需要做一个重定向, 把80端口的请求重定向到443端口,我们在Nginx配置文件的上一个代码块基础上增加一个server节点提供重定向服务
1. server {
2. listen 80;
3. server_name www.你的域名.cn;
4. rewrite ^(.*)$ https://${server_name}$1 permanent;
5. }
如此,我们通过http协议访问网站时会自动重定向到https
第一次接触wss本以为只要在nginx里面做配置即可,但是我们想想nginx只帮我们做一个代理转发的功能,实际上要想websocket支持wss协议,我们就必须让我们的web服务支持https协议,所以继续在我们的后端服务器做配置
第二步:Springboot内置tomcat配置ssl
接下来就要使用tomcat文件下的jks文件了
将证书复制到项目中并进行配置
打开我们的项目目录,在src->main->resources中,把我们刚刚的证书文件放进去
打开application配置文件,添加如下代码
其中key-store: 填写你的pfx证书文件,比如key-store: classpath:1234567_baidu.cn.pfx
key-store-password: 填写pfx-password.txt文件中的密码
(注意!!!每个属性的分号后面必须加个空格,比如port: 443,而不是port:443)
server:
port: 443
ssl:
key-store: classpath:15XXXXXXXXXX.cn.pfx
key-store-type: PKCS12
key-store-password: 这里填pfx-password.txt的文件内容(如果没有则填证书申请时的秘钥)
或者使用application.properties添加的内容如下(与上二选一即可):
我们启动试试:发现启动协议为https即配置成功
到这里我们就可以测试一波了,当然我相信你启动的时候会有各种环境依赖问题 哈哈哈哈哈~~~~
websocket在线测试工具: Websocket在线测试-Websocket接口测试-Websocket模拟请求工具
成功截图:
当然有朋友就会问了,这样我们该模块下的其它接口就只能通过https来访问了,其实我们还可通过后端配置让其也支持http请求,当然可根据业务需求还确认。
如果也要使用HTTP,可以加入以下代码,将HTTP重定向到HTTPS(如果业务不需要可不需要以下步骤了)
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfig
{
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(httpConnector());
return tomcat;
}
@Bean
public Connector httpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
//Connector监听的http的端口号
connector.setPort(8080);
connector.setSecure(false);
//监听到http的端口号后转向到的https的端口号
connector.setRedirectPort(443);
return connector;
}
}
附上我遇到的一个依赖问题,无法加载jks文件,修改pom文件新增插件配置
org.springblade blade-service2.8.0.RELEASE true 4.0.0 blade-websocket${project.artifactId} ${bladex.project.version} jar org.springblade blade-core-bootorg.springblade blade-starter-swaggercn.hutool hutool-all5.5.4 com.github.pagehelper pagehelper-spring-boot-starter1.2.5 junit junit4.12 org.springframework spring-websocket5.0.8.RELEASE compile javax.websocket javax.websocket-api1.1 provided chat src/main/resources true *.keystore *.jks *.*.jks *.p12 src/main/resources false *.keystore *.*.jks *.jks *.p12 org.apache.maven.plugins maven-resources-plugin3.1.0 org.apache.maven.plugins maven-dependency-plugincopy-dependencies package copy-dependencies ${project.build.directory}/lib false false false true runtime
其实你会发现配置不难,是各种环境报错而走的很多弯路,本文分享希望可以帮助到您,点赞哦!
完整配置参考:
server {
listen 1888;
server_name pingan.net www.pingan.net; # 填写自己的域名
rewrite ^(.*) https://www.$server_name$1:1888 permanent; # 地址重写http----https
}
server {
listen 443 ssl; #https监听端口
server_name www.pingan.net;
charset utf-8;
# ssl on;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate /etc/nginx/1_pingan.net_bundle.crt;
ssl_certificate_key /etc/nginx/2_pingan.net.key;
location / {
root /data/app/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location /api/ {
proxy_pass http://localhost/;
}
# 本地服务websokcet通讯接口
location /websocket/ {
proxy_pass http://www.pingan.net:9001; # 填写自己的域名 代理到http
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# 默认60s断开连接
proxy_read_timeout 60s;
}
}



