部署单页应用 SPA 时,我们通常使用 Nginx 做中间层进行转发代理。为了保护 Web 安全,要求我们使用 HTTPS(HTTP + SSL) 以及 WSS(Websocket + SSL) 进行通信。HTTPS 及 WSS 协议旨在保护用户数据在网络上不被窃听(机密性) 和不被篡改(完整性)。
![](https://img-blog.csdnimg.cn/img_convert/29e8036241f92f85e0c4186a52edf1e1.png)
HTTP 与 HTTPS 区别
- HTTPS 协议需要到 CA 申请证书,一般免费证书较少,因而需要一定费用;
- HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输;
- HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者默认是80,后者默认是443;
- HTTP 的连接很简单,是无状态的;HTTPS 协议是由 SSL + HTTP 协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
第一步、Nginx 配置https及wss
SSL证书
进入腾讯云服务器 - 搜索SSL证书 - 证书管理- 申请免费的SSL证书
审核通过将证书下载到本地解压,解压结果获得5个文件,如下图:
![](https://img-blog.csdnimg.cn/img_convert/4f3bb129d6c80b502e94a80d83677dd7.png)
通过Nginx配置证书,我们只需Nginx文件下的证书文件和私钥文件传到服务器, 并放到Nginx的配置文件路径
-
1_www.sitven.cn_bundle.crt
证书文件
-
2_www.sitven.cn.key
私钥文件(注意:如果在申请或者购买ssl证书设置了秘钥,则该文件不存在,配置使用之前设置的密码即可)
配置文件路径:/usr/local/nginx/conf (此处为默认安装目录,请根据实际情况操作)
![](https://img-blog.csdnimg.cn/img_convert/7f930b3a08d16b4b25adbd727ea0e22f.png)
配置NGINX
编辑 Nginx 根目录下的配置文件nginx.conf
文件。修改内容如下:
注:此操作可通过执行 vim /usr/local/nginx/conf/nginx.conf
命令行编辑该文件。由于版本问题,配置文件可能存在不同的写法
例如:Nginx 版本为 nginx/1.15.0
以上请使用 listen 443 s
sl
代替 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
就会提示没有这样的文件,如下图:
![](https://img-blog.csdnimg.cn/img_convert/bf1de9a991ca8e849b8310eca5ed7ae4.png)
我们根据错误提示将证书与私钥放到正确的路径后重新进行验证
若配置不存在问题,如下图:
![](https://img-blog.csdnimg.cn/img_convert/55fc855a07dc78d95b7c5fe02048d55d.png)
我们重启 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文件了
![](https://img-blog.csdnimg.cn/img_convert/50021f241a43aed0f6f877a9f33983ce.png)
将证书复制到项目中并进行配置
打开我们的项目目录,在src->main->resources中,把我们刚刚的证书文件放进去
![](https://img-blog.csdnimg.cn/img_convert/e2341f79bc8f2d4cfd2c03d4bf522829.png)
打开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://img-blog.csdnimg.cn/img_convert/6a587674f3d315ee8d783353c76c14b3.png)
我们启动试试:发现启动协议为https即配置成功
![](https://img-blog.csdnimg.cn/img_convert/97253e5b85982c261ed36f21eb805a31.png)
到这里我们就可以测试一波了,当然我相信你启动的时候会有各种环境依赖问题 哈哈哈哈哈~~~~
websocket在线测试工具: Websocket在线测试-Websocket接口测试-Websocket模拟请求工具
成功截图:
![](https://img-blog.csdnimg.cn/img_convert/d9c11768065a66ff8454c7d6bb52fa94.png)
当然有朋友就会问了,这样我们该模块下的其它接口就只能通过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;
/**
* http重定向到https
* @return
*/
@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文件新增插件配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springblade</groupId>
<artifactId>blade-service</artifactId>
<version>2.8.0.RELEASE</version>
</parent>
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-websocket</artifactId>
<name>${project.artifactId}</name>
<version>${bladex.project.version}</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.4</version>
</dependency>
<!--pagehelper分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--websocket-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.0.8.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>chat</finalName>
<!--依赖-->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>*.keystore</exclude>
<exclude>*.jks</exclude>
<exclude>*.*.jks</exclude>
<exclude>*.p12</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>*.keystore</include>
<include>*.*.jks</include>
<include>*.jks</include>
<include>*.p12</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<!-- 间接依赖也拷贝 -->
<excludeTransitive>false</excludeTransitive>
<!-- 带上版本号 -->
<stripVersion>false</stripVersion>
<overWriteReleases>false</overWriteReleases>
<overWriteIfNewer>true</overWriteIfNewer>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
</build>
</project>
其实你会发现配置不难,是各种环境报错而走的很多弯路,本文分享希望可以帮助到您,点赞哦!
完整配置参考:
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;
}
}