全網https測試小結

tomcat方案配置

證書生成:使用jdk提供的keytool命令,例如:nginx

keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "E:\tomcat.keystore"

非springboot項目

修改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

springboot項目

修改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;
    }
}

nginx方案配置

證書生成:使用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狀態。

相關文章
相關標籤/搜索