在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。
同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略限制以下几种行为:
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM和JS对象无法获得
- AJAX 请求不能发送
目录
什么是跨域?
为啥浏览器要限制跨域访问呢?
为什么要跨域?
怎么解决跨域呢?
跨域资源共享(CORS)
什么是跨域?
跨域是指从一个域名的网页去请求另一个域名的资源。比如从 www.baidu.com 页面去请求 www.google.com 的资源。但是一般情况下不能这么做,它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域.
所谓同源是指,域名,协议,端口均相同,只要有一个不同,就是跨域。
注意:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
URL格式由三部分组成:协议 存有该资源的主机IP地址 主机资源的具体地址
为啥浏览器要限制跨域访问呢?
原因就是安全问题
如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。比如下面的操作就有安全问题:
1.用户访问www.mybank.com ,登陆并进行网银操作,这时cookie啥的都生成并存放在浏览器
2.用户突然想起件事,并迷迷糊糊地访问了一个邪恶的网站 www.xiee.com这时该网站就可以在它的页面中,拿到银行的cookie,比如用户名,登陆token等,然后发起对www.mybank.com 的操作。
3.如果这时浏览器不予限制,并且银行也没有做响应的安全处理的话,那么用户的信息有可能就这么泄露了。
网站使用cookie的目的是为了辨别用户身份、记录用户的登录状态、跟踪统计用户访问该网站的习惯、识别用户身份、保存客户信息等1。通过保存在用户本地终端上的数据,网站可以获得访客的精准画像,提供精准的产品信息,提高页面的转化率以及延迟页面的停留时间,从而改善和加快用户的网站体验。 --百度百科
为什么要跨域?
既然有安全问题,那为什么又要跨域呢? 有时公司内部有多个不同的子域,比如一个是location.company.com ,而应用是放在app.company.com , 这时想从 app.company.com去访问 location.company.com 的资源就属于跨域。
怎么解决跨域呢?
前端解决
9种常见的前端跨域解决方案(详解) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/81809258
本文是一篇java文章,主张于从后端方面解决跨域问题;
后端
跨域资源共享(CORS)
W3C 的 Web 工作组推荐了一种新的机制,即跨域资源共享(Cross-origin Resource Sharing),简称CORS。其实这个机制就是实现了跨站访问控制,使得安全地进行跨站数据传输成为可能。
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许ajax进行跨域的访问。
只需要在后台中加上响应头来允许域请求!在被请求的Response header中加入设置,就可以实现跨域访问了!
创建过滤器实现后端设置允许跨域访问:
一个java后端过滤器:
@WebFilter(urlPatterns = "/*")
public class CorsFilter implements Filter {public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;//允许携带Cookie时不能设置为* 否则前端报错httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("origin"));//允许所有请求跨域httpResponse.setHeader("Access-Control-Allow-Methods", "*");//允许跨域的请求方法GET, POST, HEAD 等httpResponse.setHeader("Access-Control-Allow-Headers", "*");//允许跨域的请求头httpResponse.setHeader("Access-Control-Allow-Credentials", "true");//是否携带cookiefilterChain.doFilter(servletRequest, servletResponse);}
}