How does Java solve cross domain problems

  • 2021-08-31 08:12:41
  • OfStack

Catalogue introduction
What is Cross Domain (CORS)
What happens across domains
Solutions
Front-end solution
Back-end solution
Specific ways
1. Set up using Filter
2. Inherit HandlerInterceptorAdapter3. Implement WebMvcConfigurer4. Use Nginx Configuration 5. Use @ CrossOrgin Annotation
Spring Cloud Gateway cross-domain configuration

Introduction

In the development process, we often encounter cross-domain problems caused by the separation of front and back ends, which leads to the inability to obtain return results. Cross-domain is like a gap separating the front end and the back end. You are here, she is there, and you can't come and go in pairs.

What is Cross Domain (CORS)

Cross-domain (CORS) refers to the mutual access between different domain names. Cross-domain means that the browser cannot execute scripts of other websites, which is caused by the browser's homologous policy and is the security restriction policy defined by the browser for JavaScript.

What happens across domains

Same 1 protocol, such as http or https Same as 1IP address, such as 127.0. 0.1 Same port, such as 8080

If one of the above three conditions is different, cross-domain problems will arise.

Solutions

Front-end solution

Using JSONP to realize cross-domain call; The NodeJS server is used as the service proxy, the front end initiates the request to the NodeJS server, and the NodeJS server proxy forwards the request to the back end server;

Back-end solution

nginx Reverse Proxy Solving Cross-Domain The server sets Access-Control-Allow-Origin of Response Header (response header) Set cross-domain access allowed in classes and methods that require cross-domain access (such as using the @ CrossOrigin annotation in Spring); Inherit CorsFilter using Spring Web (for Spring MVC, Spring Boot) Implement the WebMvcConfigurer interface (for Spring Boot)

Specific ways

1. Set up using Filter

The Filter filter is used to filter the service request, and the Access-Control-Allow-Origin property of Response Header (response header) is set to the requesting side to declare that cross-domain access is allowed.


@WebFilter
public class CorsFilter implements Filter { 

  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
    HttpServletResponse response = (HttpServletResponse) res; 
    response.setHeader("Access-Control-Allow-Origin", "*"); 
    response.setHeader("Access-Control-Allow-Methods", "*"); 
    response.setHeader("Access-Control-Max-Age", "3600"); 
    response.setHeader("Access-Control-Allow-Headers", "*");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    chain.doFilter(req, res); 
  } 
}

2. Inheriting HandlerInterceptorAdapter


@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "*");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    return true;
  }
}

3. Implement WebMvcConfigurer


@Configuration
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
public class AppConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**") //  Intercept all requests 
        .allowedOrigins("http://www.abc.com") //  Domain name that can be cross-domain, which can be  *
        .allowCredentials(true)
        .allowedMethods("*")  //  Allow cross-domain methods, which can be configured separately 
        .allowedHeaders("*"); //  Allow cross-domain request headers, which can be configured separately 
  }
}

4. Use Nginx configuration


location / {
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Headers X-Requested-With;
  add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

  if ($request_method = 'OPTIONS') {
   return 204;
  }
}

5. Use @ CrossOrgin annotations

You can use this method if you only want some interfaces to cross domains and do not want to use configuration to manage them

Used in Controller


@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {

	@GetMapping("/{id}")
	public User get(@PathVariable Long id) {
		
	}

	@DeleteMapping("/{id}")
	public void remove(@PathVariable Long id) {

	}
}

Use on a specific interface


@RestController
@RequestMapping("/user")
public class UserController {

	@CrossOrigin
	@GetMapping("/{id}")
	public User get(@PathVariable Long id) {
		
	}

	@DeleteMapping("/{id}")
	public void remove(@PathVariable Long id) {

	}
}

Spring Cloud Gateway Cross Domain Configuration


spring: 
 cloud:
  gateway:
   globalcors:
    cors-configurations:
     '[/**]':
      #  Allow cross-domain sources ( Website domain name /ip) , setting * For all 
      #  Allow the in the cross-domain request head Field, setting * For all 
      #  Allow cross-domain method ,   Default to GET And OPTIONS , setting * For all 
      allow-credentials: true
      allowed-origins:
       - "http://xb.abc.com"
       - "http://sf.xx.com"
      allowed-headers: "*"
      allowed-methods:
       - OPTIONS
       - GET
       - POST
       - DELETE
       - PUT
       - PATCH
      max-age: 3600

Note: Pass gateway Other items forwarded, do not configure cross-domain configuration

Sometimes it doesn't work even if it is configured. At this time, you can view the problem according to the error output controlled by the browser. If the prompt is response Medium header A duplicate Access-Control-* request header appears, and you can do the following


import java.util.ArrayList;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component("corsResponseHeaderFilter")
public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {

 @Override
 public int getOrder() {
  //  Specifies that this filter is located in the NettyWriteResponseFilter After 
  //  That is to say, after the response body is processed, the response header is processed 
  return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
 }

 @Override
 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  return chain.filter(exchange).then(Mono.defer(() -> {
   exchange.getResponse().getHeaders().entrySet().stream()
     .filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
     .filter(kv -> (
       kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
         || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
         || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)
         || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS)
         || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)))
     .forEach(kv -> {
      kv.setValue(new ArrayList<String>() {{
       add(kv.getValue().get(0));
      }});
     });
   return chain.filter(exchange);
  }));
 }
}

These are the details of how Java solves cross-domain problems. For more information about Java solving cross-domain problems, please pay attention to other related articles on this site!


Related articles: