Https系列會在下面幾篇文章中分別作介紹:
一:https的簡單介紹及SSL證書的生成
二:https的SSL證書在服務器端的部署,基於tomcat,spring boot
三:讓服務器同時支持http、https,基於spring boot
四:https的SSL證書在Android端基於okhttp,Retrofit的使用
所有文章會優先在:
微信公眾號“顏家大少”中發布
轉載請標明出處
前面已介紹了:”https在服務器端的部署,基於tomcat,spring boot“
但我們會發現一個問題,只能用https登錄我們的網站,而不能用http
假設我們的網站名為:www.my.com
如果是之前的http,我們只需在瀏覽器中輸入:my.com
瀏覽器就會自動登錄到:http:// www.my.com
但部署了https后,發現在瀏覽器中輸入:my.com,返回的結果是:無法訪問此網站
這對用戶來說,體驗是非常不好的。
好吧,那我們試試一些比較有名的網站,如阿里雲。
在瀏覽器中輸入:aliyun.com
就能自動跳轉到:https: //www.aliyun.com
那我們能不能在部署了https后,在輸入:my.com
自動跳轉到https對應的: https:// www.my.com
或
依然跳轉到:http:// www.my.com ?
答案是,上面兩種方法都可以的,任君選擇
下面介紹的就是以上要求基於spring boot的實現
直接上代碼:
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.Autowired;
import org.springframework.boot.CommandLineRunner;
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 ServerMain implements CommandLineRunner{
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
@Override
protected void postProcessContext(Context context) {
//Due to CONFIDENTIAL and /*, this will cause Tomcat to redirect every request to HTTPS.
//You can configure multiple patterns and multiple constraints if you need more control over what is and is not redirected.
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");
//Set the scheme that will be assigned to requests received through this connector
//@param scheme The new scheme
connector.setScheme("http");
//Set the port number on which we listen for requests.
// @param port The new port number
connector.setPort(80);
//Set the secure connection flag that will be assigned to requests received through this connector.
//@param secure The new secure connection flag
//if connector.setSecure(true),the http use the http and https use the https;else if connector.setSecure(false),the http redirect to https;
connector.setSecure(false);
//redirectPort The redirect port number (non-SSL to SSL)
connector.setRedirectPort(443);
return connector;
}
public static void main(String[] args) throws Exception {
SpringApplication.run(ServerMain.class, args);
}
@Override
public void run(String... arg0) throws Exception {
// TODO Auto-generated method stub
}
}
其中,下面代碼的作用是把此EmbeddedServletContainerFactory 注入到web容器中
@Bean
public EmbeddedServletContainerFactory servletContainer()
然后,用下面的代碼攔截所有的/*請求
@Override
protected void postProcessContext(Context context) {
..........
constraint.setUserConstraint("CONFIDENTIAL");
collection.addPattern("/*");
.............
}
並把其關聯到下面的httpConnector中
@Bean
public Connector httpConnector()
最后,在public Connector httpConnector()中,
把http設為默認的80端口,並把http的請求跳轉到443的https端口
其中443是https的默認端口,也可以設為其它的值,但要和resources/application.properties的內容對應
如下:
server.port=443
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=123456
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias:tomcat
運行服務器,會看到打印如下:
其中會看到TomcatEmbeddedServletContainer,和同時開啟的兩個端口:443 (https) 80 (http)
TomcatEmbeddedServletContainer : Tomcat started on port(s): 443 (https) 80 (http)
Ok,那現在試試輸入:my.com,就會發現瀏覽器會直接跳到:https:// www.my.com了
到此,這件事情就算是大功告成了。
但此時有同學可能會提出特殊的要求:
他的https只是為了某某的要求而使用的,比如說要接入什么什么的一定要填的是https的地址
而他的網站根本就不需要https這種安全級別的,另外,他覺得http的訪問速度可能會快點,你知到有些同學是有這種潔癖的 :p
也就是說:
輸入:my.com,跳到: http:// www.my.com
輸入:https:// www.my.com,跳到:https:// www.my.com
要實現此要求,其實很簡單,只需要把:
@Bean
public Connector httpConnector() {
........
connector.setSecure(false);
...........
改為
@Bean
public Connector httpConnector() {
........
connector.setSecure(true);
...........
就大功告成了
更多內容請看:Https系列之四:https的SSL證書在Android端基於okhttp,Retrofit的使用
更多內容,請關注微信公眾號:顏家大少