java后端解决请求跨域
跨域
跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域
解决方式:
- 服务端设置Response Header(响应头部)的Access-Control-Allow-Origin
- 在需要跨域访问的类和方法中设置允许跨域访问(如Spring中使用@CrossOrigin注解);
- 继承使用Spring Web的CorsFilter(适用于Spring MVC、Spring Boot)
- 实现WebMvcConfigurer接口(适用于Spring Boot)
使用Filter方式进行设置
使用Filter过滤器来过滤服务请求,向请求端设置Response Header(响应头部)的Access-Control-Allow-Origin属性声明允许跨域访问。
@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);
}
}
继承 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;
}
}
实现 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("*"); // 允许跨域的请求头,可以单独配置
}
/**
* 页面跨域访问Controller过滤
*
* @return
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
WebMvcConfigurer.super.addCorsMappings(registry);
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("Get", "HEAD", "POST", "PUT", "DELECT","OPTIONS")
.allowedOrigins("*");
}
}
使用@CrossOrigin注解
如果只是想部分接口跨域,且不想使用配置来管理的话,可以使用这种方式
在Controller使用
@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public User get(@PathVariable Long id) {
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
}
}
在具体接口上使用
@RestController
@RequestMapping("/user")
public class UserController {
@CrossOrigin
@GetMapping("/{id}")
public User get(@PathVariable Long id) {
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
}
}