At work, how to solve cross-domain problems?


In an actual project, the front-end and back-end are divided into two different projects, and each is deployed under a different domain name, which will also encounter cross-domain problems.

Now that the problem has occurred, it is necessary to solve the problem fundamentally. Before we start talking about the solution, we need to understand what cross-domain is.

What is cross domain?

Cross-domain means that browsers cannot execute scripts from other websites. It is caused by the browser's same-origin policy, which is a security restriction imposed by the browser on JavaScript.

What is the Same Origin Policy?

The so-called homology refers to: the protocol, domain name, and port number are all the same, as long as one of them is different, then they are all non-same origin.

The same-origin policy is a security policy proposed by Netscape. It is the core and most basic security function of the browser. If the same-origin policy is missing, the normal functions of the browser may be affected. Now all browsers that support JavaScript will use this strategy.

When the browser executes a script, it will check which page the script belongs to, that is, check whether it is of the same origin, and only scripts of the same origin will be executed; when a script of a non-same origin requests data, the browser will report an exception , prompting access denied.

  • http://www.a.com/index.htmlThe invocation http://www.a.com/user.jspprotocol, domain name, and port number are all the same, with the same source.

  • https://www.a.com/index.htmlThe invocation http://www.a.com/user.jspprotocols are different and not of the same origin.

  • http://www.a.com:8080/index.htmlThe calling http://www.a.com:8081/user.jspports are different and not of the same origin.

  • http://www.a.com/index.htmlThe calling http://www.b.com/user.jspdomain names are different and not of the same origin.

  • http://localhost:8080/index.htmlCall http://127.0.0.1:8080/user.jspAlthough localhost is equivalent to 127.0.0.1, it is also non-same origin.

Situations restricted by the same-origin policy:

  1. Cookies, LocalStorage and IndexDB cannot be read

  2. DOM and Js objects cannot be obtained

  3. AJAX request could not be sent

Note: The src attributes of tags such as img, iframe, and script are special cases, and they can access resources of non-same-origin websites.

cross domain process

d962ac838197193520f073411ac9393.png

Example of cross-domain access

Suppose there are two websites, website A is deployed on: http://localhost:8080local ip port 8080; website B is deployed http://localhost:8081on local ip port 8081.

Now the page of website B wants to visit the information of website A, the page is displayed as follows:

image.png

It can be seen from the error message that a cross-domain problem has occurred above!

How to solve the cross-domain problem?

1. Filter

Use the Filter filter to filter service requests, and set the Access-Control-Allow-Origin attribute of the Response Header (response header) to the requester 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. Inherit 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("/**")  // 拦截所有的请求
                .allowedOrigins("http://www.abc.com")  // 可跨域的域名,可以为 *
                .allowCredentials(true)
                .allowedMethods("*")   // 允许跨域的方法,可以单独配置
                .allowedHeaders("*");  // 允许跨域的请求头,可以单独配置
    }
}

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 @CrossOrginannotations

If you only want some interfaces to cross domains and do not want to use configuration to manage, you can use this method

Use 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) {
    
    

	}
}

Summarize

Front-end solution

  1. Use JSONP to implement cross-domain calls.
  2. Use the NodeJS server as a service proxy, the front-end initiates a request to the NodeJS server, and the NodeJS server proxy forwards the request to the back-end server.

backend solution

  • Nginx reverse proxy solves cross domain
  • Server settings Response Header(response header) Access-Control-Allow-Origin.
  • Allow cross-domain access in classes and methods that require cross-domain access (such as using @CrossOriginannotations in Spring).
  • Inherit and use Spring Web's CorsFilter (applicable to Spring MVC, Spring Boot).
  • Implement the WebMvcConfigurer interface (for Spring Boot).

Guess you like

Origin blog.csdn.net/jiang_wang01/article/details/131366267