在项目开发中,不可避免会遇到跨域问题!本文简述下遇到跨域解决办法:

什么是跨域

首先,我们需要了解一下一个URL是怎么组成的:

// 协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址

1
http: + // + www.baidu.com + :8080/

只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。

    随着前后端分离开发的越来越普及,会经常遇到跨域的问题,比如用ajax从`http://localhost:8080/test.html`页面向后台接口`http://localhost:8888/user/list`发起请求,
由于两个url端口不同,所以属于跨域,在console打印台会报No 'Access-Control-Allow-Origin' header is present on the requested resource

解决跨域的几种方案

方法一:JSONP

前端使用ajax,将dataType设置成jsonp,这里不做太多说明!

重点通过 跨域访问技术CORS Cross-Origin Resource Sharing来解决的,具体的实现原理不做深入的探究,目的是解决跨域问题~

方法二:注解

在Spring Boot 中给我们提供了一个注解@CrossOrigin来实现跨域,这个注解可以实现方法级别的细粒度的跨域控制。我们可以在类或者方法上添加该注解,如果在类上添加该注解,该类下的所有接口都可以通过跨域访问,如果在方法上添加注解,那么仅仅只限于加注解的方法可以访问。

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {
@Autowired
private UserService userService;

@RequestMapping("/findAll")
public Object findAll(){
return userService.list();
}
}

方法三:实现WebMvcConfigurer

这里可以通过实现WebMvcConfigurer接口中的addCorsMappings()方法来实现跨域。

1
2
3
4
5
6
7
@Configuration
class CORSConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

方法四:Filter

我们可以通过实现Fiter接口在请求中添加一些Header来解决跨域的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class CORSFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Credentials", "true");
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
response.getWriter().println("ok");
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}

Nginx配置解决跨域问题

如果我们在项目中使用了Nginx,可以在Nginx中添加以下的配置来解决跨域(原理其实和Filter类似,只不过把活儿丢给了运维🤔)

1
2
3
4
5
6
7
8
9
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;
}
}