前言:本地Springboot+vue项目之前一直采用的http以及netty整合的websocket;但是突然要改造为https
一、改造https
因为https必须要使用证书,再加上我是本地项目,故采用自签证书,我这里是使用的mkcert构建的,具体构建过程内容你们可以参考 链接: https://cloud.tencent.com/developer/article/2379654 我这里就不详细展示。
server:
tomcat:
uri-encoding: UTF-8
threads:
max: 1000
min-spare: 30
port: 8806
ssl:
enabled: true
key-password: changeit
key-store: classpath:xxxxxx.p12
key-store-password: changeit
key-store-type: PKCS12
p12证书我是放到了resources目录下,配置则是在application.yml中进行如下配置
const path = require('path')
const fs = require('fs')
module.exports = {
devServer: {
open: true,
port: 8001,
disableHostCheck: true,
overlay: {
errors: true,
warnings: true
},
https: {
cert: fs.readFileSync(path.join(__dirname, './ssl/xxxxx.pem')),
key: fs.readFileSync(path.join(__dirname, './ssl/xxxxxx-key.pem'))
},
},
}
秘钥文件配置在了前端自定义的ssl目录下,然后再vue.config.js中配置
自此本地就能进行安全的https访问了
二、额外开放http端口
项目已经改造成了https,但是有客户端需要从我这边拿取数据,客户端也无法修改,因此开放http端口用于客户端拿取数据
首先需要在后端application.yml中配置
http:
port: 8809
然后需要新增以下代码:
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.websocket.server.WsSci;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpConfig {
@Value("${http.port}")
private int httpPort;
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
@Override
public void customize(ConfigurableWebServerFactory factory) {
if (factory instanceof TomcatServletWebServerFactory) {
TomcatServletWebServerFactory webServerFactory = (TomcatServletWebServerFactory)factory;
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
// 设置http访问的端口号,不能与https端口重复,否则会报端口被占用的错误
connector.setPort(httpPort);
webServerFactory.addAdditionalTomcatConnectors(connector);
}
}
};
}
}
客户端就可以通过8809这个端口号用http获得数据了
三、ws改造为wss
因为本地项目还使用了netty整合的websocket,前端使用的ws;但是因为http改成了https,所以ws无法使用必须改成wss,尝试过直接将ws改成wss,在断点调试中发现后端可以接收到前端的请求,但是握手不成功;
在参考链接: https://blog.csdn.net/weixin_45486926/article/details/129798118 后得以解决,文章中其他内容我们已经完成,主要解决wss前后端无法通信问题,主要参考的1.4配置改动,我这边配置如下,主要是后端需要添加内容。
首先需要新增如下代码:
package com.wocaring.modules.monitor.websocket;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
public class Sslutil {
/**
* @param type 证书类型
* @param path 证书路径
* @param password 证书密码
* @throws Exception
*/
public static SSLContext createSSLContext(String type , String path , String password) throws Exception {
InputStream inputStream = new FileInputStream(path);
char[] passArray = password.toCharArray();
SSLContext sslContext = SSLContext.getInstance("SSLv3");
KeyStore ks = KeyStore.getInstance(type);
//加载keytool 生成的文件
ks.load(inputStream, passArray);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, passArray);
sslContext.init(kmf.getKeyManagers(), null, null);
inputStream.close();
return sslContext;
}
}
然后就是你需要找到后端接收前端发送wss请求的代码位置,通常会以initChannel作为方法名,可以全局搜索initChannel,然后加入以下代码
@Override
protected void initChannel(SocketChannel sc) throws Exception {
System.out.println("收到了新的请求");
SSLContext sslContext = Sslutil.createSSLContext("PKCS12","C:\\ysk\\prod\\ssl\\192.168.0.167.p12","changeit");
//SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
SSLEngine engine = sslContext.createSSLEngine();
engine.setUseClientMode(false); //服务器端模式
engine.setNeedClientAuth(false); //不需要验证客户端
sc.pipeline().addFirst("ssl", new SslHandler(engine));
...
...
...
}
到此ws就改造成wss成功
四、额外内容
项目不止本地项目运行,因为后面还需要进行部署到其他环境,前端使用的nginx,因此在nginx.conf文件进行以下内容配置:
server {
listen 443 ssl;
server_name xxxx;
ssl_certificate C:/ysk/nginx-1.21.4/conf/xxxxx.pem;
ssl_certificate_key C:/ysk/nginx-1.21.4/conf/xxxxx-key.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root dist地址;
index index.html index.htm;
}
}