springboot+vue+nginx 配置Https访问——自签名证书验证
这段时间做的项目慢慢往移动端方向偏了,哈哈快成为复合型人才了。
问题:移动(或pc)端打开浏览器实现扫一扫识别扫描内容的功能
一看这个需求,这不简单嘛,网上例子随便一找一大堆。。。比如类似原生js实现 MediaDevices.getUserMedia()、引用zxing扫描二维码识别内容 等等。
于是兴高采烈的拿过来用了,但是发现都报错,源于:getUserMedia is not implemented in this browser, 然后再搜索查看解决方法,有人是这么说的
end:显然第二种方案不可取,不可能让用户为了适应应用去配置东西,我都嫌麻烦,更别说用户了。
所以采用第一种:http换成https协议
咱的项目是:springboot+vue,那需要怎样做呢?
1. https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
免费的证书例如在:阿里云、腾讯云上都有,搜索:SSL证书。我当时想着有点麻烦啊,但申请就申请吧,毕竟咱的项目还是要部署到线上的。
但是申请没那么简单,需要公网域名和服务器!因为过程中有一步是要验证的(dns、或文件验证),像咱这无权无势的码农就别想了,果断ps。
2. 使用本地自签证书,不安全但功能可以实现啊,目前先这样做吧
SpringBoot
JDK中keytool是一个证书管理工具,可以生成自签名证书。 本人这里用的系统是windows,cmd打开命令黑窗口,然后生成命令如下(找不到keytoo命令的先去配置java环境) 我指定的名字叫tomcat.keystore 别名叫tomcat,密码自己设置,我这里用的tomcat,最后那个直接按得回车,执行后提示你输入密码、账户等信息,随便输入无所谓。
D://是生成证书保存路径,tomcat.keystore生成证书的名字和后缀
keytool -genkey -alias tomcat -keyalg RSA -keystore D:/tomcat.keystore
将生成的文件tomcat.keystore拷贝到项目的src/main/resources资源目录下,yml或properties文件中配置如下
# 证书文件 server.ssl.key-store=classpath:tomcat.keystore # 证书密码 server.ssl.key-password=123456 # 证书类型(可以不配置) server.ssl.key-store-type=JKS # 证书别名(可以不配置) server.ssl.key-alias=tomcat
另外补充一点:以下可配置为http、https共同使用,实现思路是监听http请求转发到https请求
package com.bisp.common.config; 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.beans.factory.annotation.Value; 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; /** * @ClassName TomcatConfig * @Description TODO * @Author yzx * @Date 2022/11/24 10:59 **/ @Configuration public class TomcatConfig { /**获取配置端口*/ @Value("${server.port}") private Integer httpPort; @Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(){ @Override protected void postProcessContext(Context context) { SecurityConstraint constraint = new SecurityConstraint(); constraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); constraint.addCollection(collection); context.addConstraint(constraint); } }; factory.addAdditionalTomcatConnectors(tomcatConnector()); return factory; } private Connector tomcatConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); //http端口号,可以自行指定(不能和其它已经使用的端口重复,否则会报错) //设置http的监听端口为80端口,这样访问的时候也可以不用带上端口号 connector.setPort(9090); connector.setSecure(false); //监听到的http的端口号后转向到https的端口号,可以自行指定 connector.setRedirectPort(httpPort); return connector; } }
Vue
- 修改vue项目根路径下的vue.config.js文件,添加 https: true
module.exports = { devServer: { https: true, // 启动项目为http协议,加入这句话即可 }
- 修改请求后台接口url的 http:// 改为 https://(仅供参考)
完成以上两点后启动vue,不出所料还是报错。。
这是我们发现浏览器没有找到可信任的ssl证书,所以提示不安全,我们点击高级——继续前往,看似好像也没什么问题
但是我们在调用后台接口url时,不出所料还是报错...这就回到了本文开头的问题,就是还是说浏览器不信任该证书...
那怎么办?进退两难了?正规的证书没钱买,自签的证书又不信任,于是我又开始大量寻找答案
- 有的人说复制接口url地址到浏览器新标签页,再次打开信任就好了,这不投机取巧,没解决根本问题么
- 还有的说把本地证书安装到浏览器插件中,那不回到本文开头的问题嘛
- 或者配置axios忽略证书校验
- 或者配置vue信任本地证书
但都行不通!后来看到一个正确的解释是这样的
无奈vue开启https协议到此,我们转到nginx配置ssl证书
Nginx
- 下载 nginx windows 版本并解压,这里不过多描述
- 下载 OpenSSL windows 版本并安装,这里不过多描述
- 添加 C:\OpenSSL-Win64, C:\nginx-1.16.1 到环境变量 PATH 路径;
- 在C:\nginx-1.16.1目录下创建ssl目录,以后自签名证书存到这个目录;
- 启动 cmd 命令行程序,切到 C:\nginx-1.16.1\ssl 目录,开始创建证书。
-
基本思路是先创建服务器私钥,再创建CSR文件,最后用私钥签发CSR文件得到服务器公钥证书。
C:\nginx-1.16.1\ssl>openssl genrsa -des3 -out server.key 2048 创建服务器私钥 Generating RSA private key, 2048 bit long modulus (2 primes) ...............+++++ .........................................................................+++++ e is 65537 (0x010001) Enter pass phrase for server.key: Verifying - Enter pass phrase for server.key: C:\nginx-1.16.1\ssl>openssl req -new -key server.key -out server.csr 创建CSR证书请求文件 Enter pass phrase for server.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:CN State or Province Name (full name) [Some-State]:Shanghai Locality Name (eg, city) []:Shanghai Organization Name (eg, company) [Internet Widgits Pty Ltd]:XXXXX Organizational Unit Name (eg, section) []:Software Common Name (e.g. server FQDN or YOUR name) []:YYYY Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: C:\nginx-1.16.1\ssl>copy server.key server.key.orig 备份有秘密的私钥文件 已复制 1 个文件。 C:\nginx-1.16.1\ssl>openssl rsa -in server.key -out server.key 去掉私钥文件的密码 Enter pass phrase for server.key: writing RSA key C:\nginx-1.16.1\ssl>openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt 使用服务器私钥签署服务器公钥证书 Signature ok subject=C = CN, ST = Shanghai, L = Shanghai, O = Intel, OU = Software, CN = server1 Getting Private key
-
- 部署自签证书到nginx服务器
-
用记事本编辑 C:\nginx-1.16.1\conf\nginx.conf文件,向文件末尾追加 https 服务器配置:
# 二级路由跳转、接口代理、https信任自签证书 server { server_name 192.168.43.20; listen 443 ssl; # 监听443端口, 开启ssl(必须) # 引用ssl证书(必须,如果放在nginx/conf/ssl下可以用相对路径,其他位置必须用绝对路径) ssl_certificate ../ssl/server.crt; ssl_certificate_key ../ssl/server.key; # 协议优化(可选,优化https协议,增强安全性) ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # 二级路由跳转 location /ayyingyong20221119 { try_files $uri $uri/ /ayyingyong20221119/index.html; index index.html; } # 当遇到/api (也就是我们的接口)对其进行反向代理 location /ayyingyong20221119/api { proxy_pass https://localhost:9090/ayyingyong20221119/api; } }
-
- 重启 nginx 然后在浏览器输入 https://192.168.43.20/ayyingyong20221119 看看
-
nginx -s reload
或打开任务管理器先停止nginx服务,再双击启动服务
-
并且我们的后台服务也正常调用,当然获取摄像头权限也是没问题的,大功告成!
同理,移动端同pc端效果是一样的,因为具有摄像头就可以实现效果预览。
随着移动端的发展,越来越多的开发app内嵌webview 。很多时候本地浏览器没问题,放在app里却问题频出,为了准确的把锅丢给app开发,我们就要掌握移动端请求抓包的技法!!!
这里推荐大家一个好用的工具 Fiddler Everywhere :可以运行在任何浏览器,任何系统、跨平台(Windows、Mac、Linux)的一款Web调试代理工具。它记录了计算机和Internet之间的所有HTTP(S)通信,可以检查和编辑通信,并拥有Mock请求以及修改响应返回的能力。
好用的前端组件 Vant:轻量、可靠的移动端 Vue 组件库开发团队,注意区别 vue2、vue3 版本