一、概念
1、为什么要使用证书
对数据进行签名(加密)是我们在网络中最常见的安全操作。签名有双重作用,作用一就是保证数据的完整性,证明数据并非伪造,而且在传输的过程中没有被篡改,作用二就是防止数据的发布者否认其发布了该数据。
签名同时使用了非对称性加密算法和消息摘要算法,对一块数据签名时,会先对这块数据进行消息摘要运算生成一个摘要,然后对该摘要使用发布者的私钥进行加密。 比如微信公众平台开发中最常见的调用api接口方法是将参数进行字典序排序,然后将参数名和参数值接成一个字符串,组合的字符串也就相当于我们这里说的摘要,然后将摘要用平台密钥加密。
接收者(客户端)接受到数据后,先使用发布者的公钥进行解密得到原数据的摘要,再对接收到的数据计算摘要,如果两个摘要相同,则说明数据没有被篡改。同时,因为发布者的私钥是不公开的,只要接收者通过发布者的公钥能成功对数据进行解密,就说明该数据一定来源于该发布者。
那么怎么确定某公钥一定是属于某发布者的呢?这就需要证书了。证书由权威认证机构颁发,其内容包含证书所有者的标识和它的公钥,并由权威认证机构使用它的私钥进行签名。信息的发布者通过在网络上发布证书来公开它的公钥,该证书由权威认证机构进行签名,认证机构也是通过发布它的证书来公开该机构的公钥,认证机构的证书由更权威的认证机构进行签名,这样就形成了证书链。证书链最顶端的证书称为根证书,根证书就只有自签名了。总之,要对网络上传播的内容进行签名和认证,就一定会用到证书。关于证书遵循的标准,最流行的是 X.509
2、SSL协议
SSL(Secure Socket Layer,安全套接层):是为网络通信提供安全及数据完整性的一种安全协议。SSL位于TCP/IP协议与各种应用层协议之间,为数据通信提供安全支持。SSL协议分为两层:1)SSL记录协议,建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持;2)SSL握手协议,建立在SSL记录协议之上,用于在实际数据传输开始前,通信双方进行身份认证、协商加密算法、交换加密密钥等。
二、SpringBoot配置SSL
1、生成证书
keytool -genkey -alias tomcat -keyalg RSA -keystore /Users/zhanghao/Desktop/tomcatkeystore.keystore -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN" -keypass 123qwe
参数说明:
-genkey:表示要创建一个新的密钥
-alias:和keystore关联的别名,这个alias通常不区分大小写,默认“mykey”
-keyalg:使用加密的算法,这里是RSA,默认“DSA”
-keystore:密钥保存的文件位置,默认“用户宿主目录中名为 .keystore 的文件,没有不会新建,所以还是指定的好”
-dname:表明了密钥的发行者身份
CN=commonName 注:生成证书时,CN要和服务器的域名相同,如果在本地测试,则使用localhost
OU=organizationUnit
O=organizationName
L=localityName
S=stateName
C=country
-keypass:私有密钥的密码,这里设置为“123qwe”
其他参数
-storepass :存取密码(我用的mac jdk1.8.0_131 不支持这个参数)
-validity:密钥的有效期,默认为90天(我用的mac jdk1.8.0_131 不支持这个参数)
-keysize 1024(没用过)
-file 读时为标准输入,写时为标准输出 (没用过)
注:cacerts证书文件(The cacerts Certificates File),存在于$JAVA_HOME\jre\lib\security目录下,是Java系统的CA证书仓库
2、SpringBoot配置SSL
1)将证书文件复制到项目的根目录
2)配置文件
server:
port: 8080
ssl:
key-store: tomcatkeystore.keystore
key-store-password: 123qwe
key-store-type: JKS
key-alias: tomcat
http访问
https访问
3、配置http自动转向https
1)端口配置
http:
port: 8080
server:
port: 8443
2)端口监听转换
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpsConfig {
@Value("${http.port}")
private int httpPort;
@Value("${server.port}")
private int serverPort;
@Bean
public TomcatServletWebServerFactory 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.setPort(httpPort);
connector.setSecure(false);
connector.setRedirectPort(serverPort);
return connector;
}
}
请求http://localhost:8080则自动重定向到https://localhost:8443