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