为什么会有跨域问题
浏览器拒绝执行其它域名下的 ajax 运作:
我想自己做一个搜索网站,但我不会搜索技术,怎么办呢?如果能发起 ajax 请求到百度就好了呢,可以这样吗?
肯定不行,如果浏览器在自己的服务器域名对应的 html 页面内,发起 ajax 请求偷盗 www.baidu.com 域名下的内容来填充自己的页面,整个互联网秩序将混乱。
为了防止这种混乱,W3C 组织制定了浏览器安全规范,即 html 页面发起的 ajax 请求仅限于同域名后端范围,跨越域名的ajax请求不得执行,此谓跨域问题
从程序员的角度来看,当发生跨域时,浏览器的控制台会给出没有 “Access-Control-Allow-Origin” 的报错。
解决方法
方案一:Nginx 配置
方案二:Filter 配置
利用 servlet 规范
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/*
* value、origins属性:配置允许访问的源,如: http://anxminise.cc,*表示允许全部的域名
methods属性:配置跨域请求支持的方式,如:GET、POST,且一次性返回全部支持的方式
maxAge属性:配置预检请求的有效时间, 单位是秒,表示:在多长时间内,不需要发出第二次预检请求
allowCredentials属性:配置是否允许发送Cookie,用于 凭证请求, 默认不发送cookie
allowedHeaders属性:配置允许的自定义请求头,用于 预检请求
exposedHeaders属性:配置响应的头信息, 在其中可以设置其他的头信息,不进行配置时, 默认可以获取到Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma字段
*
* */
@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", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
@Override
public void destroy() {
}
}
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//父容器
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{SpringContainer.class};
}
//SpringMVC配置子容器
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{MvcContainer.class};
}
//获取DispatcherServlet的映射信息
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected Filter[] getServletFilters() {
CorsFilter corsFilter = new CorsFilter();
return new Filter[]{corsFilter};
}
}
为什么这么写有用,见 Spring5 源码阅读笔记(5)基于注解的方法替换 web.xml
方案三:@EnableWebMvc 配置
原理上,用的 Spring 里的 Interceptor
@Configuration
@EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/user/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT","PATCH")
.maxAge(3600);
}
}
方案四:@CrossOrigin 配置
在方法上添加注解,也可以
@CrossOrigin(origins = "*"
,allowedHeaders = "x-requested-with"
,allowCredentials = "true"
,maxAge = 3600
,methods = {RequestMethod.GET,RequestMethod.POST,RequestMethod.OPTIONS,RequestMethod.DELETE})