给前后端分离vue+springboot项目配置SSL证书


参考:
Nginx 服务器 SSL 证书安装部署
浏览器报Mixed Content错误的解决
使用SpringBoot配置https(SSL证书)
配置SpringBoot同时支持http和https访问
Springboot配置SSL(https)
Nginx配置同一个域名同时支持http与https两种方式访问。

申请证书

1、腾讯云/阿里云申请免费 ssl 证书

image.png

2、下载证书

下载 Tomcat(JKS)、Nginx 证书,解压。格式:域名_nginx域名_jks
image.png

前端 nginx 配置

我的 vue 项目是放到 docker 的 nginx 容器运行的

1、拷贝证书

找到 nginx 证书的 xxx_bundle.crt 证书文件和 xxx.key 私钥文件,拷贝到 nginx 容器(我的容器名是 vueblog_frontend)的 /etc/nginx 目录下。(我的 nginx 版本是 1.21)

docker cp heart-go.cn_bundle.crt vueblog_frontend:/etc/nginx/
docker cp heart-go.cn.key vueblog_frontend:/etc/nginx/

2、进入 nginx 容器修改配置

docker exec -it vueblog_frontend /bin/bash
cd /etc/nginx/conf.d/
vim default.conf

若没有 vim,可以 apt-get install vim 安装一个。

nginx 配置如下,修改为你的域名和证书名。
image.png
保存退出。

测试 nginx

$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

3、重载 nginx 配置

nginx -s reload

到这里前端 vue 项目的 ssl 证书就配置完了。

4、端口映射

exit 退出容器,给 nginx 容器添加一个 443 的端口映射
docker 给运行的容器加端口映射

curl 也正常。
image.png

5、配置 nginx 让 http 访问自动跳转到 https

http 是不安全的连接,一般都推荐使用 https。

所以我们在用户使用 http 访问网站的时候,做一个跳转。

打开nginx配置

docker exec -it vueblog_frontend /bin/bash
cd /etc/nginx/conf.d/
vim default.conf

注释掉原有 server 的 80 端口监听
image.png

添加一个新的 server 配置,监听80端口并重定向到 https 访问地址。
image.png

让配置生效

nginx -t
nginx -s reload

此时使用 http 访问网站,就会自动跳转到 https 地址。

后端 springboot 项目配置 SSL 证书

此时用 https 访问我们的前端 vue 项目,出现了后端接口调用失败的情况。

在浏览器 console 看到报错:

Mixed Content: The page at 'https://heart-go.cn/login' was loaded over HTTPS, but requested an insecure resource 'http://xxx'. This request has been blocked; the content must be served over HTTPS.

https 地址中,如果加载了 http 资源,浏览器将认为这是不安全的资源,将会默认阻止。

我们之前的后端接口是直接 http协议://ip:端口 调用的,现在也得支持 ssl 访问才行。

1、修改前端接口请求地址

在配置之前,先把前端项目的接口请求地址修改一下。
http 改成 https,ip 改成域名。
image.png

2、证书文件扔到 resource

然后打开后端 springboot 项目,把我们下载的 Tomcat(JKS)证书里的 xxx.jks 证书文件扔到 resource 下。
image.png

3、修改 springboot 配置文件

修改你的项目配置文件 application.properties
server.ssl.key-store 是你的证书路径
server.ssl.key-store-password 是你下载的证书里 keystorePass.txt 文件的内容

注意不是 server.ssl.key-password

image.png

4、docker 容器端口映射

然后新建一个配置类,做一下端口映射,添加一个新的 8082 端口另外支持 http 访问。

package com.libaiyun.config;

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;
import org.apache.catalina.connector.Connector;

/**
 * SSL访问端口映射
 */
@Configuration
public class SSLConfig {

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(createHTTPConnector());
        return tomcat;
    }

    private Connector createHTTPConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        //同时启用http(8082)、https(8081)两个端口
        connector.setScheme("http");
        connector.setSecure(false);
        connector.setPort(8082);
        connector.setRedirectPort(8081);
        return connector;
    }
}

5、测试

打包上线,此时我们可以 curl https 监听端口

curl https://heart-go.cn/8081

或者 curl http 监听端口

curl http://heart-go.cn/8082

都可以正常访问后端接口。(如果是 docker 运行的话记得给新增的 http 端口 8082 也添加映射~)

本地生成 SSL 证书并给 springboot 配置

除了上述申请受信任机构的 ssl 证书,我们也可以选择自己本地生成一个。(二选一即可)

1、生成密钥证书

打开cmd,执行

keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650

keytool 是 jdk 的工具,安装好 jdk 可以找到

alias:密钥别名
storetype:指定密钥仓库类型
keyalg:生成证书的算法名称,RSA是一种非对称加密算法
keysize:证书大小
keystore:生成的证书文件的存储路径
validity:证书的有效期

接着输入证书密码(记下)、证书信息(随意填,浏览器中查看证书时会显示)
image.png

2、配置 springboot

将生成的密钥证书拷贝到项目中的 resource 中
image.png

修改项目配置文件 application.properties

server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=证书密码
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=tomcat

启动访问即可,注意这种本地生成的 SSL 证书放到浏览器上会显示不受信任的机构颁发的证书。
image.png

当然仅用于后端接口 ssl 支持,则无需在意。

SSL 相关

1、ssl 证书是带有域名/IP 信息的

记住我们的 ssl 证书是带有域名/IP 信息的,如果

curl https://121.4.119.108:8081

或者

curl https://localhost:8081

这样的形式,都是会出现 ssl 错误的,因为域名和证书对不上。

$ curl https://121.4.119.108:8081
curl: (60) schannel: SNI or certificate check failed: SEC_E_WRONG_PRINCIPAL > (0x80090322) - 目标主要名称不正确。
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

当然我们给 curl 加上 -k 参数就可以忽略 ssl 错误正常访问。

体现到前端访问上,ssl 错误就会显示网站不安全。
image.png

当然只是作为后端接口调用,其实也没什么问题。我们依旧可以用 ip 作为 HTTPS 接口地址。

2、一个端口同时只支持一种协议

一个端口同时只支持一种协议,比如上面我们监听 8081 使用ssl协议,监听 8080 使用 http 协议。

HTTP 协议是应用层的,端口是传输层,数据从高到低层层封包,传输过去再由低到高层层解包,这部分可以去看下 OSI 七层模型和 TCP/IP 模型及对应协议

如果我们使用 HTTP 协议去访问 HTTPS 端口,就会出错

$ curl http://121.4.119.108:8081/
Bad Request
This combination of host and port requires TLS.

反之,我们使用 HTTPS 协议去访问 HTTP 端口,也会报错

$ curl https://121.4.119.108:8082/
curl: (35) schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x80090308) - 给函数提供的标志无效

如果想让一个端口同时支持 HTTP 和 HTTPS 访问,就得用到 nginx 了。
Nginx 实现一个端口同时支持 HTTP 和 HTTPS 访问

over

到这里后端配置 SSL 也结束,我们把前后端项目都上线,测试正常访问。

原创文章,作者:,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/273320.html

(0)
上一篇 2022年7月10日 05:33
下一篇 2022年7月10日 05:33

相关推荐

发表回复

登录后才能评论