Article Directory
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.html
The invocationhttp://www.a.com/user.jsp
protocol, domain name, and port number are all the same, with the same source. -
https://www.a.com/index.html
The invocationhttp://www.a.com/user.jsp
protocols are different and not of the same origin. -
http://www.a.com:8080/index.html
The callinghttp://www.a.com:8081/user.jsp
ports are different and not of the same origin. -
http://www.a.com/index.html
The callinghttp://www.b.com/user.jsp
domain names are different and not of the same origin. -
http://localhost:8080/index.html
Callhttp://127.0.0.1:8080/user.jsp
Although localhost is equivalent to 127.0.0.1, it is also non-same origin.
Situations restricted by the same-origin policy:
-
Cookies, LocalStorage and IndexDB cannot be read
-
DOM and Js objects cannot be obtained
-
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
Example of cross-domain access
Suppose there are two websites, website A is deployed on: http://localhost:8080
local ip port 8080; website B is deployed http://localhost:8081
on local ip port 8081.
Now the page of website B wants to visit the information of website A, the page is displayed as follows:
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 @CrossOrgin
annotations
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
- Use JSONP to implement cross-domain calls.
- 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
@CrossOrigin
annotations in Spring). - Inherit and use Spring Web's CorsFilter (applicable to Spring MVC, Spring Boot).
- Implement the WebMvcConfigurer interface (for Spring Boot).