同源策略禁止读取位于_一文带你走进同源策略以及CORS

上一篇文章带大家了解了SSO的相关内容,这篇文章针对我在实现SSO的demo中额外学的同源策略以及CORS做一个记录。

同源策略和CORS

同源策略

什么是同源策略?

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

何为同源?
  • 协议相同

  • 域名相同

  • 端口相同

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

同源策略的三个方面
  1. Cookie同源策略:不同源cookie不共享

  2. DOM同源策略:禁止对不同源的页面dom操作,主要针对的是iframe跨域

  3. XmlHttpRequest同源策略:禁止使用XmlHttpRequet向不同域发起请求,例如ajax请求

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

<html><head>    <title>AJAX跨域测试title>    <script src="js/jquery.min.js">script>head><body><button class="btn">请求baidubutton><script>    $(".btn").click(function(){        $.ajax({            url:"http://www.baidu.com",            type:"get"        })    })script>body>html>

点击button,ajax发起跨域请求

看一下Chrome显示

4ed06bc5b64e64c1be3a87578fe36112.png

火狐

538ce8949061051e2832332b6aaa8e00.png

为何要有同源策略

同源策略的目的就是保障用户的信息安全,防止恶意网站窃取数据,下面通过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的头字段不能超出以下几个

AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-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请求,并且添加了相关字段

1e41b51fbc8b70b9fc9384824123e678.png

发送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请求,就和普通请求一样了。

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

@Overridepublic 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/blog/2016/04/cors.html

https://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

https://juejin.im/post/6844903681683357710#comment

------------------

最后

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

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

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

公众号: 小白不想当码农

945ca7b9cb06d67ffde9a523da3f650d.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值