Cấu hình Spring Boot chuyển hướng HTTP sang HTTPS
1. Sử dụng cả hai HTTP và HTTPS
Theo mặc định ứng dụng Spring Boot chỉ sử dụng một trong hai giao thức HTTP hoặc HTTPS. Câu hỏi đặt ra là làm thế nào để sử dụng đồng thời cả hai giao thức này.
Mở file application.properties và thêm vào property server.http.port để định nghĩa một cổng dành cho HTTP, và property server.port định nghĩa một cổng cho HTTPS.
Chú ý: server.http.port là một property do bạn định nghĩa, và nó không sẵn có trong SpringBoot.
application.properties (*)
# (User-defined Property)
# Port for HTTP and read by Spring Boot via @Value("${server.http.port:80}")
server.http.port=8080
# Port for HTTPS and read by Spring Boot via @Value("${server.port:443}")
server.port=8443
server.ssl.key-store=file:/home/tran/SSL/o7planning.org/o7planning_org.p12
server.ssl.key-store-password=P@ssword
server.ssl.key-alias=o7planning
Tiếp theo, tạo một lớp HttpHttpsConfigV1 và cấu hình cho phép Spring Boot sử dụng đồng thời cả 2 giao thức http và https.
HttpHttpsConfigV1.java
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpHttpsConfigV1 {
// (User-defined Property)
@Value("${server.http.port:80}")
private int httpPort;
@Bean
public ServletWebServerFactory servletContainer() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setPort(this.httpPort);
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(connector);
return tomcat;
}
}
2. Redirect HTTP to HTTPS (Way 2)
Mục đích chính của việc cấu hình Spring Boot cho nó hỗ trợ cả hai giao thức HTTP và HTTPS là làm cho ứng dụng có thể nhận được các yêu cầu (request) gửi tới thông qua HTTP và tự động chuyển hướng (redirect) nó tới HTTPS.
application.properties (*)
# (User-defined Property)
# Port for HTTP and read by Spring Boot via @Value("${server.http.port:80}")
server.http.port=8080
# Port for HTTPS and read by Spring Boot via @Value("${server.port:443}")
server.port=8443
server.ssl.key-store=file:/home/tran/SSL/o7planning.org/o7planning_org.p12
server.ssl.key-store-password=P@ssword
server.ssl.key-alias=o7planning
Bây giờ chúng ta sẽ tạo ra một phiên bản thứ hai, lớp HttpHttpsConfigV2 thay thế cho lớp HttpHttpsConfigV1, nó cho phép ứng dụng Spring Boot của bạn có thể sử dụng cả hai giao thức HTTP và HTTPS nhưng tất cả các request với giao thức HTTP sẽ tự động được chuyển hướng (redirect) tới HTTPS:
HttpHttpsConfigV2.java
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.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpHttpsConfigV2 {
// IMPORTANT!!!
// If this parameter is empty then do not redirect HTTP to HTTPS
//
// Defined in application.properties file
@Value(value = "${server.ssl.key-store:}")
private String sslKeyStore;
// Defined in application.properties file
// (User-defined Property)
@Value(value = "${server.http.port:80}")
private int httpPort;
// Defined in application.properties file
@Value("${server.port:443}")
int httpsPort;
@Bean
public ServletWebServerFactory servletContainer() {
boolean needRedirectToHttps = sslKeyStore != null && !sslKeyStore.isEmpty();
TomcatServletWebServerFactory tomcat = null;
if (!needRedirectToHttps) {
tomcat = new TomcatServletWebServerFactory();
return tomcat;
}
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(redirectConnector());
return tomcat;
}
private Connector redirectConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(httpPort);
connector.setSecure(false);
connector.setRedirectPort(httpsPort);
return connector;
}
}
3. Redirect HTTP to HTTPS (Way 3)
Trong một số trường hợp bạn muốn Spring Boot hỗ trợ cả hai giao thức HTTP và HTTPS, và chỉ tự động chuyển hướng từ HTTP đến HTTPS với các đường dẫn (path) được chỉ định, điều này có thể làm được với Interceptor.
application.properties (*)
# (User-defined Property)
# Port for HTTP and read by Spring Boot via @Value("${server.http.port:80}")
server.http.port=8080
# Port for HTTPS and read by Spring Boot via @Value("${server.port:443}")
server.port=8443
server.ssl.key-store=file:/home/tran/SSL/o7planning.org/o7planning_org.p12
server.ssl.key-store-password=P@ssword
server.ssl.key-alias=o7planning
Lớp HttpHttpsConfigV3 cho phép ứng dụng Spring Boot sử dụng đồng thời cả hai giao thức HTTP và HTTPS:
HttpHttpsConfigV3.java
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// @see HttpHttpsInterceptor
@Configuration
public class HttpHttpsConfigV3 {
@Value("${server.http.port:80}")
private int httpPort;
@Bean
public ServletWebServerFactory servletContainer() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setPort(this.httpPort);
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(connector);
return tomcat;
}
}
Interceptor là một lớp nằm giữa người dùng và Controller, nó có thể từ chối, sửa đổi, hoặc chuyển hướng request của người dùng. Dựa trên khả năng này của Interceptor bạn có thể sử dụng nó để phát hiện các HTTP Request và chuyển hướng chúng sang HTTPS.
HttpHttpsInterceptor.java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class HttpHttpsInterceptor implements HandlerInterceptor {
// Defined in application.properties file
@Value(value = "${server.ssl.key-store:}")
private String sslKeyStore;
// Defined in application.properties file
@Value(value = "${server.http.port:80}")
private int httpPort;
// Defined in application.properties file
@Value("${server.port:443}")
int httpsPort;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// @return http or https
String schema = request.getScheme();
// System.out.println("Schema: " + schema);
if("https".equals(schema)) {
return true;
}
if(sslKeyStore == null || sslKeyStore.isEmpty()) {
return true;
}
String serverName = request.getServerName();
// System.out.println("Server Name: " + serverName);
boolean isIP = this.isIP(serverName);
// System.out.println("isIP: " + isIP);
if (isIP) {
// System.out.println("No Redirect isIP = "+ isIP);
return true;
}
int requestedPort = request.getServerPort();
// System.out.println("requestedPort: " + requestedPort);
if (requestedPort == httpPort) { // This will still allow requests on :8080
// System.out.println("Redirect to https");
String queryString = request.getQueryString();
if (queryString == null || queryString.isEmpty()) {
if (httpsPort == 443) {
response.sendRedirect(
"https://" + request.getServerName() + request.getRequestURI());
} else {
response.sendRedirect(
"https://" + request.getServerName() + ":" + httpsPort + request.getRequestURI());
}
} else {
if (httpsPort == 443) {
response.sendRedirect(
"https://" + request.getServerName() + request.getRequestURI() + "?" + queryString);
} else {
response.sendRedirect(
"https://" + request.getServerName() + ":" + httpsPort + request.getRequestURI() + "?" + queryString);
}
}
return false;
}
return true;
}
private boolean isIP(String remoteHost) {
String s = remoteHost.replaceAll("\\.", "");
// System.out.println("isIP? " + s);
try {
Long.parseLong(s);
} catch (Exception e) {
// e.printStackTrace();
return false;
}
return true;
}
}
Cuối cùng bạn cần đăng ký lớp HttpHttpsInterceptor với Spring Boot và chỉ rõ các đường dẫn (path) nào sẽ phải đi qua Interceptor này, nghĩa là chúng sẽ bị chuyển hướng tới HTTPS, các đường dẫn khác sẽ sử dụng cả hai giao thức HTTP và HTTPS.
WebMvcConfig.java
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@Transactional
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private HttpHttpsInterceptor httpHttpsInterceptor;
//
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(httpHttpsInterceptor);
registry.addInterceptor(httpHttpsInterceptor)//
.addPathPatterns("/path01", "path02/**");
}
// Other configs ...
}
Các hướng dẫn Spring Boot
- Cài đặt Spring Tool Suite cho Eclipse
- Hướng dẫn lập trình Spring cho người mới bắt đầu
- Hướng dẫn lập trình Spring Boot cho người mới bắt đầu
- Các thuộc tính thông dụng của Spring Boot
- Hướng dẫn sử dụng Spring Boot và Thymeleaf
- Hướng dẫn sử dụng Spring Boot và FreeMarker
- Hướng dẫn sử dụng Spring Boot và Groovy
- Hướng dẫn sử dụng Spring Boot và Mustache
- Hướng dẫn sử dụng Spring Boot và JSP
- Hướng dẫn sử dụng Spring Boot, Apache Tiles, JSP
- Sử dụng Logging trong Spring Boot
- Giám sát ứng dụng với Spring Boot Actuator
- Tạo ứng dụng web đa ngôn ngữ với Spring Boot
- Sử dụng nhiều ViewResolver trong Spring Boot
- Sử dụng Twitter Bootstrap trong Spring Boot
- Hướng dẫn và ví dụ Spring Boot Interceptor
- Hướng dẫn sử dụng Spring Boot, Spring JDBC và Spring Transaction
- Hướng dẫn và ví dụ Spring JDBC
- Hướng dẫn sử dụng Spring Boot, JPA và Spring Transaction
- Hướng dẫn sử dụng Spring Boot và Spring Data JPA
- Hướng dẫn sử dụng Spring Boot, Hibernate và Spring Transaction
- Tương tác Spring Boot, JPA và cơ sở dữ liệu H2
- Hướng dẫn sử dụng Spring Boot và MongoDB
- Sử dụng nhiều DataSource với Spring Boot và JPA
- Sử dụng nhiều DataSource với Spring Boot và RoutingDataSource
- Tạo ứng dụng Login với Spring Boot, Spring Security, Spring JDBC
- Tạo ứng dụng Login với Spring Boot, Spring Security, JPA
- Tạo ứng dụng đăng ký tài khoản với Spring Boot, Spring Form Validation
- Ví dụ OAuth2 Social Login trong Spring Boot
- Chạy các nhiệm vụ nền theo lịch trình trong Spring
- Ví dụ CRUD Restful Web Service với Spring Boot
- Ví dụ Spring Boot Restful Client với RestTemplate
- Ví dụ CRUD với Spring Boot, REST và AngularJS
- Bảo mật Spring Boot RESTful Service sử dụng Basic Authentication
- Bảo mật Spring Boot RESTful Service sử dụng Auth0 JWT
- Ví dụ Upload file với Spring Boot
- Ví dụ Download file với Spring Boot
- Ví dụ Upload file với Spring Boot và jQuery Ajax
- Ví dụ Upload file với Spring Boot và AngularJS
- Tạo ứng dụng Web bán hàng với Spring Boot, Hibernate
- Hướng dẫn và ví dụ Spring Email
- Tạo ứng dụng Chat đơn giản với Spring Boot và Websocket
- Triển khai ứng dụng Spring Boot trên Tomcat Server
- Triển khai ứng dụng Spring Boot trên Oracle WebLogic Server
- Cài đặt chứng chỉ SSL miễn phí Let's Encrypt cho Spring Boot
- Cấu hình Spring Boot chuyển hướng HTTP sang HTTPS
- Tìm nạp dữ liệu với Spring Data JPA DTO Projections
Show More