【Java应用】浏览器跨域的缘由
为什么有浏览器跨域限制
因为浏览器认为通信双方都是不可信的
跨站脚本攻击 XSS (Cross Site Scripting)
首先为什么叫XSS不叫CSS是为了避免和层叠样式表(Cascading Style Sheets, CSS)混淆
XSS是一种注入攻击,不管是哪种攻击实例,攻击人既可以通过浏览器来发起攻击也可以通过诱导用户点击钓鱼链接发起攻击。
跨站请求伪造 CSRF (Cross Site Request Forgery)
我们知道CSRF的攻击对象对于只是获取数据的请求是无效的,这里正是因为浏览器同源策略的限制,而且我们目前常见的CRFS的方法方案是验证Raferer,依然依赖于浏览器,所以我们可以看到浏览器在默认情况下是认为通信双方都是不可信的。
浏览器是如何实现跨域限制的
同源策略 SOP (Same Origin Policy)
因为浏览器认为通信双方不可信,为了限制两个域之间直接的数据交互,浏览器提供了同源策略的限制。
那怎么判定是不是同源呢?主要包括
- 协议
- 域名
- 端口
那不同源有哪些限制呢?主要包括
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM 无法获得
- AJAX 请求不能发送
跨域资源共享CORS(Cross-origin resource sharing)
同源策略虽然提高了安全性,但是也带来了可用性的问题,当确实需要有跨域的数据访问的时候就有问题了,所以W3C提出了CORS,这里需要浏览器支持,同时需要服务端配置,浏览器把请求分为两种,一种是简单请求,详细内容点击这里 ,对于简单请求,不会先发起预检请求,也就是options请求,这时候他会根据服务端的配置返回对应信息,例如:
Access-Control-Allow-Origin: http://www.test.com // 允许的域
Access-Control-Allow-Methods: GET, POST, PUT, DELETE // 允许的方法
Access-Control-Allow-Headers: X-Custom-Header // 允许的自定义字段
Access-Control-Allow-Credentials: true // 是否允许用户发送、处理
cookie Access-Control-Max-Age: 172800 // 预检请求的有效期,单位为秒。有效期内,不需要发送预检请求,ps 48小时
然后浏览器会根据你的返回值判断是否发起真正的请求,这里需要注意
在 Chrome 和 Firefox 中,如果 Access-Control-Allow-Methods 中并未允许 GET/POST/HEAD 请求,但允许跨域了,浏览器还是会允许 GET/POST/HEAD 这些简单请求访问,这时就必须在后台用其他办法禁掉这些 Method
注意
如果是在nginx这一层处理的跨域问题,对于简单请求他不会发起预检请求,直接带着origin到了后端,后端如果因为权限或业务逻辑的问题返回的状态码为401或500的话,那么前端也会显示跨域问题,因为nginx在转发server响应的过程中,add_header只有在返回状态码为200,201,204,206,301,302,303,304,307的时候才会加上