background
The reason for this article is to resolve a cross-domain request for a business center page. Because the business center, or the ability to reuse services, is now very much advocated, it is common to request resources from different domain names under the domain name of a unified business center. So this is bound to cause cross-domain problems.
Cross domain
Cross-domain actually stems from a security restriction that browsers place on javascript (also known as the same origin policy). By default, you can access only resources under the same protocol, domain name, and port.
The actual scene
The front desk of the business center has two functions. Function A needs to request the background API of the user center and the price center to complete it. Function B needs to request the API of user center, policy center, organization center and customer center.
For example, if function A requests the user center, A cross-domain problem occurs when A request is sent from bussiness.center.com to the user.com domain.
A single service across domain solution
Using Filter
In the case of the Spring Cloud Gateway, we need to add cross-domain Filter implementation logic to the Gateway. Of course, cross-domains can be handled in any Spring 5.0+ service in the following manner.
-
Interface WebFilter
package org.springframework.web.server;
// Requires Spring 5.0+
public interface WebFilter {
Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);
}
Copy the code
Interface description: Intercepting chain processing contracts for Web requests, which can be used to implement cross-domain, application-independent requirements, such as security, timeouts, etc.
There are two ways to do this according to WebFilter.
** Custom Filter implements WebFilter **
@Component
public class CorsFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
//TODO adds configuration in response header to allow cross-domain,
/ / such as Access - Control - Allow - Origin
returnwebFilterChain.filter(serverWebExchange); }}Copy the code
Spring’s self-implemented cross-domain filter CorsWebFilter is recommended for cross-domain processing
Cross-domain is handled by configuring the CorsConfigurationSource
@Bean
CorsWebFilter corsWebFilter(a) {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowedOrigins(Arrays.asList("http://allowed-origin.com"));
corsConfig.setMaxAge(8000L);
corsConfig.addAllowedMethod("PUT");
corsConfig.addAllowedHeader("Baeldung-Allowed");
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/ * *", corsConfig);
return new CorsWebFilter(source);
}
Copy the code
- InterFace GlobalFilter
The idea of using SprinCloud Gateway GlobalFilter to solve cross-domain problems is basically the same as that of self-implementing WebFiler. It is important to note that the order in which the various filters of the gateway are executed is concerned, and I recommend that you configure GlobalFilter across domains to be executed first.
@Component
public class GlobalCorsFilter implements GlobalFilter.Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //TODO adds configuration in response header to allow cross-domain,
/ / such as Access - Control - Allow - Origin
return chain.filter(exchange);
}
@Override
public int getOrder(a) {
returnOrdered.HIGHEST_PRECEDENCE; }}Copy the code
Use @crossorigin on Controller to handle cross-domains
The API for a particular Controller can be handled across domains through annotations.
@CrossOrigin(value = { "http://allowed-origin.com" }, allowedHeaders = { "Baeldung-Allowed" }, maxAge = 900 )
@RestController
public class CorsOnClassController {
@PutMapping("/cors-enabled-endpoint")
public Mono<String> corsEnabledEndpoint(a) {
// ...
}
@CrossOrigin({ "http://another-allowed-origin.com" })
@PutMapping("/endpoint-with-extra-origin-allowed")
public Mono<String> corsEnabledWithExtraAllowedOrigin(a) {
// ...
}
// ...
}
Copy the code
Enable CORS on global configuration
The addCorsMappings() method is also recommended to define the global CORS configuration by overriding the WebFluxConfigurer implementation. You need @enableWebFlux to import the Spring WebFlux configuration.
@Configuration
@EnableWebFlux
public class CorsGlobalConfiguration implements WebFluxConfigurer {
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/ * *")
.allowedOrigins("http://allowed-origin.com")
.allowedMethods("PUT")
.maxAge(3600); }}Copy the code
Cross-domain solutions for business centers
Whether it’s through Filter, adding HttpReponse Header to allow cross-domain request headers, or overriding WebFluxConfigurer to configure cross-domain. This is a good solution for a single service.
But for the front desk of the business center, it is very undesirable and very frustrating to configure so many domain names and corresponding apis for the middle Stage project.
So the establishment of the middle layer is particularly important and key. We use Nginx as a reverse proxy server to solve cross-domain problems.
Nginx. conf, upstream and server can be used to resolve cross-domain issues, load balancing, health checks, etc.
upstream user {
zone upstream_dynamic 64k;
server backend1.example.com weight=5;
server backend2.example.com:8080 fail_timeout=5s slow_start=30s;
server 192.0.2.1 max_fails=3;
server backend3.example.com resolve;
server backend4.example.com service=http resolve;
server backup1.example.com:8080 backup;
server backup2.example.com:8080 backup;
}
upstream policy {
zone upstream_dynamic 64k;
server backend1.example.com weight=5;
server backend2.example.com:8080 fail_timeout=5s slow_start=30s;
server 192.0.2.1 max_fails=3;
server backend3.example.com resolve;
server backend4.example.com service=http resolve;
server backup1.example.com:8080 backup;
server backup2.example.com:8080 backup;
}
server {
listen 80;
server_name bussiness.center.com;
location /api/user {
proxy_pass http://user;
health_check;
}
location /api/policy {
proxy_passhttp://policy; health_check; }}Copy the code
Refer to the article
www.baeldung.com/spring-webf…