🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# http转https - [一、 使用JDK自带工具KeyTool 生成自签发证书!](#_JDKKeyTool__41) - [二、 springBoot http https](#_springBoot_http__https_83) - [三、haproxy负载下的https](#haproxyhttps_253) - [1. 第一种实时步骤(开发环境)](#1__277) - [2. 第二种方式:步骤如下](#2__357) - [四、pem转成KeyStore](#pemKeyStore_388) 参考: <http://blog.csdn.net/lanwenbing/article/details/24741973> <https://www.cnblogs.com/xxt19970908/p/6736370.html> [http://blog.csdn.net/zhuchunyan\_aijia/article/details/53261305](http://blog.csdn.net/zhuchunyan_aijia/article/details/53261305) **1.什么是HTTPS?** > HTTPS其实是有两部分组成:HTTP + SSL / TLS, 也就是在HTTP上又加了一层处理加密信息的模块,并且会进行身份的验证。 > 问题: > Firebug和postman之类的浏览器调试工具,为什么获取到的是明文? > 解答: > SSL是对传输的数据进行加密,针对的是传输过程的安全。 > firebug之类的浏览器调试工具, > 因为他们得到的是客户端加密之前/解密之后的数据,因此是明文的。 **2.什么是自签名证书?** > 就是自己生成的证书,并不是官方生成的证书。 > 除非是很正式的项目,否则使用自己签发的证书即可,因为官方生成证书是要花钱的。 **3. http与https对比** > 1. 不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,带来了三大风险。 > (1) 窃听风险(eavesdropping):第三方可以获知通信内容。 > (2) 篡改风险(tampering):第三方可以修改通信内容。 > (3) 冒充风险(pretending):第三方可以冒充他人身份参与通信。 > 1. SSL/TLS协议是为了解决这三大风险而设计的,希望达到: > (1) 所有信息都是加密传播,第三方无法窃 > (2) 具有校验机制,一旦被篡改,通信双方会立刻发现 > (3) 配备身份证书,防止身份被冒充。 互联网是开放环境,通信双方都是未知身份,这为协议的设计带来了很大的难度。而且,协议还必须能够经受所有匪夷所思的攻击,这使得SSL/TLS协议变得异常复杂。 ## 一、 使用JDK自带工具KeyTool 生成自签发证书! Keytool是一个Java数据证书的管理工具。Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中在keystore里,包含两种数据: ``` 1. 密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密) 2. 可信任的证书实体(trusted certificate entries)——只包含公钥 ``` Alias(别名):每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写 第一步:为服务器生成证书(使用keytool命令生成证书) ``` keytool -genkey -alias tomcat -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore ./tomcat.keystore -storepass 123456 -genkey -alias tomcat(别名) -keypass 123456(别名密码) -keyalg RSA(算法) -keysize 1024(密钥长度) -validity 365(有效期,天单位) -keystore D:/keys/tomcat.keystore(指定生成证书的位置和证书名称) -storepass 123456(获取keystore信息的密码) ``` 输入命令后提示输入: ``` What is your first and last name? #“您的名字与姓氏是什么?”这是必填项,并且必须是TOMCAT部署主机的域名或者IP[如:pvbutler.blog.51cto.com 或者 10.15.24.254],就是你将来要在浏览器中输入的访问地址 [Unknown]: 10.15.24.254 What is the name of your organizational unit? #“你的组织单位名称是什么?”可以按照需要填写也可以不填写直接回车,实验中直接回车 [Unknown]: What is the name of your organization? #“您的组织名称是什么?”,同上直接回车 [Unknown]: What is the name of your City or Locality? #“您所在城市或区域名称是什么?,同上直接回车 [Unknown]: What is the name of your State or Province? #“您所在的州或者省份名称是什么?” [Unknown]: What is the two-letter country code for this unit? #“该单位的两字母国家代码是什么?” [Unknown]: Is CN=10.15.24.254, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct? #系统询问“正确吗?”时,对照输入信息,如果符合要求则使用键盘输入字母“y”,否则输入“n”重新填写上面的信息 [no]: y ``` 得到tomcat.keystore文件 ## 二、 springBoot http https ``` 获取一个tomcat.keystore的文件,将这个文件放到项目的目录中 ``` ![](https://box.kancloud.cn/e5a655017bab95fa95cd44ba7efba8dc_450x140.png) 配置SSL 编辑application.properties这个文件 ``` server.port=8443 server.ssl.key-store=tomcat.keystore server.ssl.key-password=changeit server.ssl.key-store-type=JKS server.ssl.key-alias=tomca ``` 我这里用的是默认密码:changeit ``` http转向https ``` 1) 这里需要配置使用TomcatEmbeddedServletContainerFactory这个类在启动方法类中加入以下: 2)注意端口的修改 ``` package com.example; 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.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Bean; @SpringBootApplication public class SpringBootHttpsApplication { public static void main(String[] args) { SpringApplication.run(SpringBootHttpsApplication.class, args); } @Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() { @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); } }; tomcat.addAdditionalTomcatConnectors(httpConnector()); return tomcat; } @Bean public Connector httpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); //Connector监听的http的端口号 connector.setPort(8080); connector.setSecure(false); //监听到http的端口号后转向到的https的端口号 connector.setRedirectPort(8443); return connector; } ``` 测试使用 1、查看启动信息 ![image](https://box.kancloud.cn/76aacf533db104f5b9470e0bb4f15be2_800x296.png) 2、访问地址localhost:8080/AmazeUI-2.7.2/login.html 我自定义了一个html网页,它已经转向到了8443端口 ![image](https://box.kancloud.cn/1b1ebe14e63b355e87fbfd2ed486b171_797x397.png) 3、浏览器的地址栏中显示不安全:因为这个证书是不收信任的,传统一般都企业都是需要购买此证书的 三、 强制tomcat自动http转https 前提:按照第1步步骤生成证书(.keystore文件),tomcat版本(8.5.15) 1\.修改tomcat的server.xml,找到以下配置,取消注释并按照以下配置修改 ``` <!-- 设置https端口:31101 --> <Connector port="31101" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="/home/tuna/tomcat.keystore" <!-- 引用生成的KeyStore文件 --> keystorePass="123456"> <!-- <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA" /> </SSLHostConfig>--> </Connector> ``` 另外将 `<Connector port="31001" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/` 将http的31001转向https的31101端口 `<Connector port="31001" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="31101" URIEncoding="UTF-8"/>` 将 ``` <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" / ``` 改成(对于来自于集成的http服务器发来的请求,也转成https) ``` <Connector port="8009" protocol="AJP/1.3" redirectPort="31101" / ``` 重启后,用户也可以去掉端口同时访问http和https了 2\. 为客户端生成证书(和生成KeyStore一样) 为浏览器生成证书,以便让服务器来验证它。为了能将证书顺利导入至IE和Firefox,证书格式应该是PKCS12 `keytool -genkey -alias client1 -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -storetype PKCS12 -keystore ./client1.p12 -storepass 12345` 3\. 让服务器信任客户端证书 1) 由于不能直接将PKCS12格式的证书库导入,必须先把客户端证书导出为一个单独的CER文件,使用如下命令: keytool -export -alias client -keystore ./client.p12 -storetype PKCS12 -keypass 123456 -file ./client.cer 注意:Keypass:指定CER文件的密码,但会被忽略,而要求重新输入 2) 将该文件导入到服务器的证书库(最先生成的.keystore文件),添加为一个信任证书: ``` keytool -import -v -file D:/keys/client.cer -keystore D:/keys/tomcat.keystore -storepass 123456 ``` 3) 完成之后通过list命令查看服务器的证书库, 可以看到两个证书,一个是服务器证书,一个是受信任的客户端证书: ``` keytool -list -v -keystore ./tomcat.keystore ``` 1. 让客户端信任服务器证书 1) 由于是双向SSL认证,客户端也要验证服务器证书,因此,必须把服务器证书添加到浏览器的“受信任的根证书颁发机构”。由于不能直接将keystore格式的证书库导入,必须先把服务器证书导出为一个单独的CER文件,使用如下命令: keytool -keystore ./tomcat.keystore -export -alias tomcat -file ./server.cer 2) 双击server.cer文件,按照提示安装证书,将证书填入到“受信任的根证书颁发机构”。 填入方法: 打开浏览器 - 【工具】- 【internet选项】-【内容】- 【证书】- 【导入】把server.cer导入到“受信任的根颁发机构”就OK了。 5\. http自动转https 修改web.xml,在该文件前面面加上这样一段: ``` <login-config> <!-- Authorization setting for SSL --> <auth-method>CLIENT-CERT</auth-method> <realm-name>Client Cert Users-only Area</realm-name> </login-config> <security-constraint> <!-- Authorization setting for SSL --> <web-resource-collection > <web-resource-name >SSL</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint ``` ## 三、haproxy负载下的https **实现haproxy负载下的http请求转https主要有两种方式:** 第一种:把ssl证书设置在haproxy上 > 1、需要编译haproxy时 加入对ssl的支持 > 2、 支持对tcp四层和http七层负载均衡 > 3、解码SSL连接并发送非加密连接到后端应用tomcat,这意味着负载均衡器负责解码SSL连接,这与SSL穿透相反,它是直接向代理服务器发送SSL连接的。 第二种:把ssl证书设置在tomcat上 > 1、haproxy服务器本身只提供代理,后面的web服务器走https(配置ssl证书) > 2、失去增加或修改HTTP报头的能力,因为连接只是简单地从负载均衡器路由到tomcat服务器,这意味着应用服务器会失去获取 X-Forwarded-\* 报头的能力,这个报头包含了客户端IP地址、端口和使用的协议。 > 2、需要web端对ssl的支持(配置ssl证书) > 3、haproxy使用tcp模式把连接当作信息流来转发到其他web服务器 ### 1. 第一种实时步骤(开发环境) 安装包:链接:<https://pan.baidu.com/s/1qZyb5uO> 密码:f1cj > 192\.168.2.25 :haproxy(负载) > 192\.168.2.81:tomcat(web) > 192\.168.2.82:tomcat(web) 一、生成证书(192.168.2.25) ``` cd /root/tuna mkdir ssl cd ssl openssl genrsa -out ./timing-dev.key 2048 openssl req -new -key ./timing-dev.key -out ./timing-dev.csr openssl x509 -req -days 3655 -in timing-dev.csr -signkey timing-dev.key -out timing-dev.crt cat timing-dev.crt timing-dev.key | tee timing-dev.pem ``` 二、编译haproxy支持https setup.sh脚本中加入了 USE\_OPENSSL=1 ADDLIB=-lz对ssl的支持 ``` make TARGET=linux2628 ARCH=x86_64 USE_OPENSSL=1 ADDLIB=-lz ``` 执行脚本 ``` ./setup.sh ``` 1. 修改haproxy配置 1) 备份 ``` cp /usr/local/haproxy/conf/haproxy.cfg /usr/local/haproxy/conf/haproxy.cfg2018012 ``` 2)修改配置 ``` vim /usr/local/haproxy/conf/haproxy.cfg ``` ``` 原https配置: listen timing bind 0.0.0.0:31001 mode tcp balance source server timing1 192.168.2.81:31101 weight 1 maxconn 10000 check inter 10s server timing2 192.168.2.82:31101 weight 1 maxconn 10000 check inter 10s 修改为: frontend timing bind 0.0.0.0:31001 reqirep (.*):31001 \1 # 修改URL,否则会跳转https://xxxxxxxx:31001 redirect scheme https if !{ ssl_fc } bind 0.0.0.0:443 ssl crt /root/tuna/ssl/timing-dev.pem acl is_timing hdr(host) -i 192.168.2.25 192.168.2.25:443 use_backend timing if is_timing backend timing balance source server timing1 192.168.2.81:31001 weight 1 maxconn 10000 check inter 10s server timing2 192.168.2.82:31001 weight 1 maxconn 10000 check inter 10s ``` 3) 重启haproxy ``` service haproxy restart ``` ### 2. 第二种方式:步骤如下 一、步骤 1)把ssl证书设置在tomcat处 参考web服务器对ssl的支持 ,完成其中第一项(证书的生成)和第三项( 强制tomcat自动http转https) 2)修改haproxy配置文件(以25的haproxy为例) 首先、关闭haproxy,然后修改haproxy.cfg文件 ``` listen timing bind 0.0.0.0:31001 mode http balance source server timing1 192.168.2.81:31001 weight 1 maxconn 10000 check inter 10s server timing2 192.168.2.82:31001 weight 1 maxconn 10000 check inter 10s 修改为 listen timing bind 0.0.0.0:31001 mode tcp balance source server timing1 192.168.2.81:31101 weight 1 maxconn 10000 check inter 10s server timing2 192.168.2.82:31101 weight 1 maxconn 10000 check inter 10s ``` 最后重启haproxy ## 四、pem转成KeyStore 1、生成pkcs12格式的密钥文件: ``` openssl pkcs12 -export -in timing-prod.crt -inkey timing-prod.pem -out timing-prod.pk12 -name timing # timing-prod.crt :公钥 # timing-prod.pem:包含公钥和私钥 ``` 2、生成keystore: ``` keytool -importkeystore -deststorepass '4rfv$RFV' -destkeypass '4rfv$RFV' -destkeystore timing-prod.keystore -srckeystore timing-prod.pk12 -srcstoretype PKCS12 -srcstorepass '4rfv$RFV' -alias timing ```