跨域问题及解决方式(CORS)
1. 背景2. 什么是跨域?3. 非同源限制4. 跨域解决方案4.1 cors4.2 nginx4.2 其他方式1. 背景
项目中在用图片验证码,项目重启后发现验证码无法正常使用,这让我很是头疼,刚才还好好的,咋重启了一下就没法用了。打开F12 后发现是 如下图:
当时第一想法就是需要在项目配置跨域,在排查项目过程中发现有跨域的相关配置。但是后续还是没有反应过来是IP没对上导致的,后来将localhost 换成127.0.01 后解决的。特在此写一篇博客来进行记录。
2. 什么是跨域?
跨域是指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要!!!
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;[原文][1]
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
3. 非同源限制
无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB无法接触非同源网页的 DOM法向非同源地址发送 AJAX 请求4. 跨域解决方案
4.1 cors
跨源资源共享(CORS)(或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch)使用 CORS,以降低跨源 HTTP 请求所带来的风险。
普通跨域请求:只需服务器端设置Access-Control-Allow-Origin带cookie跨域请求:前后端都需要进行设置
前端vue
vue-resource
Vue.http.options.credentials = true
vue-resource
Vue.http.options.credentials = true
后端Spring
全局配置适配器
@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")//针对header单独设置,不然无法获取header中的请求信息,前端也无法拿到响应中的 // header信息,OPTIONS请求也会经过拦截器,在进行登录拦截时候要注意特殊处理.allowedHeaders("*").exposedHeaders("access-control-allow-headers","access-control-allow-methods","access-control-allow-origin","access-control-max-age","X-Frame-Options")// 表明在3600秒内,不需要再发送预检验请求,可以缓存该结果.maxAge(3600).allowCredentials(true);}}
全局过滤器
通过实现Fiter接口在请求中添加一些Header来解决跨域的问题
@Componentpublic class CorsFilter implements Filter {@Overridepublic 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);}@Overridepublic void destroy() {}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}}
4.2 nginx
使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。
我们只需要配置nginx,在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可。这样,这个服务器上所有url都是相同的域 名、协议和端口。因此,对于浏览器来说,这些url都是同源的,没有跨域限制。而实际上,这些url实际上由物理服务器提供服务。这些服务器内的 javascript可以跨域调用所有这些服务器上的url。
4.2 其他方式
在实际开工作中CORS 较为常见,但是也有其他的解决方式。 请参考:什么是跨域?跨域解决方法
【注】:上述如有问题,请不吝赐教,如有侵权,请及时联系进行删除
参考地址:
什么是跨域?跨域解决方法
什么是跨域?如何解决?【注 nginx 如何实现】
10种跨域解决方案(附终极大招)
跨源资源共享(CORS)【注:外文翻译】