所谓难者不会,会者不难。在问题解决之后,发现很简单,但在茫无头绪之初,往往不知该从何着手,查网上资料,大多仅是实现方案的一个片段,无法贯穿整个解决方案,下面简要介绍整个解决过程。先从理论上理清。
一、开启https认证需要有CA证书,先来了解一下https认证的过程,https认证有单相认证和双向认证,如果项目没有特定要求,一般来说单向认证就可以。认证过程如下:
二、了解一下这些证书
SSL 证书格式有PEM、CER、JKS、PKCS12等类型。下面逐一说明。
1、DER .CER,文件是二进制格式,只保存证书,不保存私钥。
2、PEM,一般是文本格式,可保存证书,可保存私钥。有时我们也把PEM 格式的私钥的后缀改为 .key。这种格式常用于 Apache 和 Nginx 服务器。
3、CRT,可以是二进制格式,可以是文本格式,与 .DER 格式相同,不保存私钥。
4、PFX,二进制格式,同时包含证书和私钥,一般有密码保护。从阿里云申请的CA证书的tomcat证书就是这种格式。用来部署在项目中,如ssm项目,springboot项目。
5、JKS,Java Key Storage,二进制格式,同时包含证书和私钥,一般有密码保护。利用 JAVA 的一个叫 keytool 的工具,可以自已生成私有证书。一般用于 Tomcat 服务器。
三、CA证书的获取
CA证书可以用JAVA 的工具 keytool 自已生成(生成方式网上介绍很多,请自行查阅资料),也可以从阿里云或腾讯云平台免费申请,下面以阿里云为例介绍。
在阿里云平台申请免费CA证书后,如下:
点击下载 按钮后的页面如下:
看到这么多证书,可能会晕,不知该下载那一个。 下面就介绍一下这些证书都是什么。分两种情况举例说明:
1、如果,是ssm的java项目,也就是前后端没有分离,项目部署在tomcat下就可以运行,那么,在这里只需要下载tomcat证书,然后在tomcat的配置文件server.xml中加入:
<Connector port="8443" protocol="HTTP/1.1" maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
keystoreFile="证书的路径 / 证书文件.pfx" #这里我用的是绝对路径
keystoreType="PKCS12"
keystorePass="证书密码"
clientAuth="false"
sslProtocol="TLSv1+TLSv1.1+TLSv1.2" />
这样,就在8443端口,开启了https访问。
2、如果,是springboot + vue项目或者springboot+ uni-app项目,也就是前后端分离的项目,那就需要下载tomcat证书和前端容器需要的CA证书。如果前端是h5网页形式,一般是用nginx部署,那么就需要下载nginx的CA证书,证书分为两个文件,一个是以.key为扩展名,保存私钥;一个是以.pem为扩展名,保存证书(公钥)。
首先,先部署springboot部分。将下载的tomcat证书XXX.pfx文件,放到resources目录下面,也就是和application.yml文件同一目录,然后修改.yml配置文件如下:
server:
port: 5443 # https的端口
http:
port: 5050 # http的端口
ssl:
key-store: classpath:XXXX.pfx #类路径下的CA证书
key-store-password: 证书密码 #证书密码
然后新建配置类TomcatConfig,代码如下:
package com.xxx.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.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;
@Configuration
public class TomcatConfig {
@Value("${server.http.port}")
private int httpPort;
@Value("${server.port}")
private int httpsPort;
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(Connector connector) {
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(connector);
return tomcat;
}
@Bean
public Connector connector(){
Connector connector=new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
//http端口
connector.setPort(httpPort);
connector.setSecure(true);
// https端口,即server.port
connector.setRedirectPort(httpsPort); //重定向到htts
return connector;
}
}
然后测试是否开通https,如下:
说明 springboot部分开通https成功。这里,前端项目https可以通过发送请求。如uni-app项目,在manifest.json文件中如下所示:
以上,在开发环境中,已经可以在前后端用https协议请求和返回数据。
3、接下来解决前端h5网页通过nginx部署时,CA证书配置问题
修改nginx配置文件nginx.conf,如下:
server {
listen 443 ssl;
server_name 你的域名;
ssl_certificate ../阿里云下载的nginx证书文件.pem;
ssl_certificate_key ../阿里云下载的nginx证书文件.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root C:/project/xxx-uniapp/unpackage/dist/build/h5; #前端H5网页目录
index index.html index.htm;
}
location /proxyApi/ { #前端H5网页访问后台服务器的代理路径,在manifest.json配置的
proxy_pass https://127.0.0.1:5443/;
proxy_set_header Host $host:$server_port;
}
location /aabbbccc { #通过443端口访问的其它项目,如果没有这一段可以省去
proxy_pass https://127.0.0.1:8443/aabbbccc;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme; # 配置 X-Forwarded-Proto 就是为了正确地识别实际用户发出的协议是 http 还是 https。
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
至此,整个项目的https访问配置完成。
四、补充说明
在网上申请的CA证书,是需要绑定域名的。当在本机测试https访问时会有“证书风险”或者“不安全”等提示,但不影响访问和数据交互。在windows环境下开发,也可以用修改hosts文件的方法解决这个问题,这个文件的路径如下:C:\Windows\System32\drivers\etc
在hosts这个文件中加入一行:
127.0.0.1 你的CA证书绑定的域名
这样,在本机浏览器访问【你的CA证书绑定的域名】时,实际上是访问的本机 127.0.0.1,这时的证书与域名匹配,浏览器就不再提示风险或不安全等信息。
整个解决思路完成,希望能够对在路上摸索的同学们有所启发。