證書生成:使用jdk提供的keytool命令,例如:nginx
keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "E:\tomcat.keystore"
修改tomcat下conf/server.xml,加入:spring
<Connector SSLEnabled="true" acceptCount="100" clientAuth="false" URIEncoding="UTF-8" disableUploadTimeout="true" enableLookups="false" maxThreads="25" port="8443" keystoreFile="E:\tomcat.keystore" keystorePass="123456" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true" sslProtocol="TLS" />
其中keystoreFile爲證書存放路徑,keystorePass爲證書密碼apache
修改application.yml文件:tomcat
server.port: 8443 #https端口 server.ssl.key-store: E:/keystore.p12 #證書路徑 server.ssl.key-store-password: 123456 #證書密碼 server.ssl.keyStoreType: PKCS12 server.ssl.keyAlias: tomcat http.port: 8080#http端口
上述配置包含http端口8080和https端口8443springboot
若要既支持http請求又支持https請求,則須要添加類以下:session
@Configuration public class HttpSupport { @Value("${http.port}") private int port; @Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); tomcat.addAdditionalTomcatConnectors(createHttpConnector()); return tomcat; } private Connector createHttpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); connector.setPort(port); connector.setSecure(false); return connector; } }
若是隻支持https請求的話能夠考慮將http請求強轉成https,需添加類以下:app
@Configuration public class HttpsConfiguration { @Value("${http.port}") private int httpPort; @Value("${server.port}") private int httpsPort; @Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() { @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(initiateHttpConnector()); return tomcat; } private Connector initiateHttpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); connector.setPort(httpPort); connector.setSecure(false); connector.setRedirectPort(httpsPort); return connector; } }
證書生成:使用openssl命令
修改nginx.conf文件:ide
server { listen 443; server_name localhost; ssl on; ssl_certificate D:/nginx/ssl/lee.crt; ssl_certificate_key D:/nginx/ssl/lee.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 5m; ssl_protocols SSLv3 TLSv1; ssl_ciphers HIGH:!ADH:!EXPORT56:RC4+RSA:+MEDIUM; ssl_prefer_server_ciphers on; location / { proxy_pass http://xxx.xx.x.xx:8080; proxy_set_header Host $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
修改server.xml配置,在模塊下添加:post
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
注意:因爲反向代理用了7層轉發,因此:url
request.getScheme() //老是 http,而不是實際的http或https request.isSecure() //老是false(由於老是http) request.getRemoteAddr() //老是 nginx 請求的 IP,而不是用戶的IP request.getRequestURL() //老是 nginx 請求的URL 而不是用戶實際請求的 URL response.sendRedirect( 相對url ) //老是重定向到 http 上 (由於認爲當前是 http 請求)
解決方案爲:如上nginx和tomcat配置
proxy_set_header Host $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
一般在反向代理那邊配X-Forwarded-For,Tomcat這邊用request.getHeader("X-Forwarded-For")拿到用戶真實IP地址。在反向代理那邊配X-Forwarded-Proto這種Header,Tomcat這邊用request.getHeader("X-Forwarded-Proto")來判斷用戶是否處於https狀態。