在?了解一下同源策略和CORS可好?

同源策略和CORS

一:同源策略

什么是同源策略?

同源策略(same-orgin policy)是一种约定,web是构建在同源策略之上的,浏览器是针对同源策略的一种实现。同源策略最初是指不同源的A网页的cookie不能被B网页的获得,后来扩展对dom操作,XmlHttpRequest也做了限制

何为同源?
  • 协议相同
  • 域名相同
  • 端口相同

只有同时满足以上三个条件才谓之同源

同源策略的三个方面
  1. Cookie同源策略:不同源cookie不共享
  2. DOM同源策略:禁止对不同源的页面dom操作,主要针对的是iframe跨域
  3. XmlHttpRequest同源策略:禁止使用XmlHttpRequet向不同域发起请求,例如ajax请求

下面看一下ajax跨域请求,浏览器的显示




 AJAX跨域测试
 





点击button,ajax发起跨域请求

看一下Chrome显示

image

火狐
image

为何要有同源策略

同源策略的目的就是保障用户的信息安全,防止恶意网站窃取数据,下面通过DOM和XmlHttpRequest来说明

如果没有Dom同源策略
  1. 现在有一个假网站,通过iframe嵌入了一个银行网站
  2. 通过设置将银行网站的宽高设置到合适比例,让这个假网站在浏览器上面除了url不同,其他都和银行网站一模一样
  3. 用户在iframe嵌套的银行网站中输入了密码和账户名称
  4. 在iframe的外层通过dom操作获得用户的密码和账户
  5. 这样用户的密码和账户信息就被窃取了
如果没有XmlHttpRequest同源策略
  1. 用户登录银行网站,提交登录表单,银行服务器通过验证,为了维持对话返回Cookie
  2. 这时用户又浏览了另一个网站,而这个网站就是一个恶意网站
  3. 恶意网站后台向银行网站发起ajax请求,请求携带第一步银行的cookie,银行服务器通过cookie验证了用户身份,响应这个假冒用户的请求
  4. 这样用户的信息又泄漏了,而且是后台发起ajax请求,所以用户不会感知到这个过程

所以在同源策略的保护下,我们可以安全的上网

CORS

跨域限制

因为同源策略,所以浏览器的跨域请求被限制,但是有些时候跨域操作又是必须的;例如在CAS实现SSO的过程中,就需要在访问子系统的时候将浏览器重定向到CAS Server。

解决方案之CORS

CORS(cross orign resource sharing)即跨域资源共享,是一个W3C标准,它允许浏览器向不同源的服务器发起XmlHttpRequest请求,从而克服了AJAX,重定向只能同源使用的限制

CORS的实现需要浏览器和服务器的同时支持,整个CORS的通信过程是在后台进行的,不需要用户的参与,浏览器会根据跨域请求,自动为请求的request header额外添加一些字段,对于部分跨域请求还会在真正发出跨域请求之前发送一个preflight请求。

目前所有的浏览器都支持CORS,IE浏览器版本不能低于IE10,所以实现CORS的关键在于服务器,我认为这也正常,因为你是跨域访问我,不是我的人,还想要的资源,肯定得征得我同意呀。

俩种请求

浏览器将CORS请求分为俩类:简单请求和非简单请求

简单请求需要同时满足以下俩个条件

  1. 请求方法是 HEAD,GET,POST之一
  2. HTTP的头字段不能超出以下几个
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type: 只限于三个值application/x-www.form-urlencded,multipart/form-data,text/plain

凡不是简单请求的都是非简单请求(废话!!!)

简单请求跨域流程

  1. 对于简单跨域请求,浏览器会直接向服务器发起请求,并且在请求头中添加Origin字段来说明源信息例如协议端口域名。
  2. 服务器可以通过这个字段来决定是否同意这次请求。Origin的源在服务器允许的范围内,那么服务器就会在response中添加一个Access-Control-Origin :true,如果服务器不允许,那么在浏览器端发现响应中没有Access-Control-Origin字段就会抛出一个错误。
  3. 默认浏览器不会跨域携带Cookie,如果需要,ajax请求需要设置属性withCredentials属性为true,服务器需要设置相应头部Access-Control-Allow-Credentials:true

非简单请求跨域流程

对于非简单跨域请求,浏览器会在真正发起请求前先发起一个Preflight请求给服务器,请求method使用OPTIONS,头部会加入下列信息

Origin : 源信息
Access-Control-Request-Method : 列出请求使用的方法
Access-Control-Request-Headers:自定义的头部信息

看一个例子,实践出真知

$(".btn").click(function(){
 $.ajax({
 url:"https://www.baidu.com",
 type:"get",
 headers:{
 "CONTENT":"TEST"
 }//添加了自定义headers,所以是非简单请求
 })
})

浏览器F12查看network,果然浏览器提前发送了preflight请求,并且添加了相关字段

在?了解一下同源策略和CORS可好?_第1张图片

发送preflight后,服务器端可以根据Origin,Access-Control-Request-Method和Access-Control-Request-Headers决定是否允许请求,当在允许的响应中会添加如下字段

Access-Control-Allow-Origin:与简单的请求相同。*代表同意任何跨域请求
Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。
Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。
Access-Control-Max-Age: 应该将这个 Preflight 请求缓存多长时间(以秒表示)。
Access-Control-Allow-Credentials: 允许携带Cookie

如果不允许,服务器返回正常的HTTP响应,但是没有任何的CORS相关的头信息,浏览器就会认定,服务器不同意预检请求,因此触发一个错误

如果允许,以后每次浏览器正常的CORS请求,就和普通请求一样了。

具体服务器可以设置一个拦截器

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 String originHeader = request.getHeader("Origin");
 response.setHeader("Access-Control-Allow-Origin", originHeader);
 response.addHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,accessToken");
 response.addHeader("Access-Control-Allow-Credentials", "true");
 response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
 return true;
}

本文参考

http://www.ruanyifeng.com/blo...

https://www.ruanyifeng.com/bl...

https://juejin.im/post/684490...


重磅资源!!!

关注小白不想当码农微信公众号。

后台回复java核心技术卷关键字领取《java核心技术卷》pdf

回复jvm领取《深入理解Java虚拟机》pdf和《自己动手写jvm

回复设计模式领取《headfirst设计模式》pdf

回复计算机网络领取《计算机网络自顶向下》pdf

最后

我是不想当码农的小白,平时会写写一些技术博客,推荐优秀的程序员博主给大家还有自己遇到的优秀的java学习资源,希望和大家一起进步,共同成长。

以上内容如有错误,还望指出,感谢

公众号点击交流,添加我的微信,一起交流编程呗!

公众号: 小白不想当码农
在?了解一下同源策略和CORS可好?_第2张图片

你可能感兴趣的:(javascript,html,chrome,java,后端)