大话跨域
文章目录
cros
what:什么是跨域?
- 我有一个域名a.com和一个域名b.com
- 我在a.com上有一个接口a.com/api,会返回一些数据
- 我想在b.com域名下的一个页面上访问a.com/api得到数据
- 浏览器阻止了我
why: 为什么不让我跨域?
因为在web交互的环境中,只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
跨站请求伪造(CSRF)
- 支付宝的转账操作是一个post请求,大概是https://alipay.com/api/withdraw/?to_user=XXX&amout=1000
- 我写了一段ajax的post请求代码,请求连接是上面的url。
- 然后我把这段代码嵌入我的网站a.com你不久前登陆过支付宝,
- 浏览器里保存了alipay.com域名的cookie
- 我让你访问a.com,打开页面,于是在你不知情的情况下发出了post请求,你的钱就被转到我的账号里了
how: 解决跨域问题:
- 发请求前设置一下document.domain的值.
- 父子域名
- JSONP—json with padding.
- 在非父子域关系的情况下,如developer.mozilla.org和production.mozilla.org(或者a.com和b.com),就是被浏览器当作两个不同的域名的,一般就会使用JSONP了.
- 跨域资源共享(CORS).
- 简单请求—GET和POST。
- 预检请求—PUT和DELETE等,或者请求时添加了CORS安全的header之外的header(如自定义的)。
- 带cookie的请求—要求响应头里
Access-Control-Allow-Credentials
为true,且Access-Control-Allow-Origin
不能是通配符,防止后端犯错。
document.domain
- 如果是子域名下的页面想访问父域的api,如developer.mozilla.org想访问mozilla.org的api,那可以在发请求前设置一下document.domain的值为mozilla.org。毕竟是子域,浏览器几乎没有做什么限制.
JSONP
- JSONP 指的是 JSON with Padding
- 从另一个域请求文件会引起问题,由于跨域政策,从另一个域请求外部脚本没有这个问题
|
|
- index.html
|
|
- server.script
|
|
JSONP缺陷
- 因为作为一个script标签:
- 一是浏览器只会使用GET方法去请求它
- 二是请求它的时候不会携带cookie
- 三是能被改造成JSONP形式的api一定是纯粹用来GET数据的.
一是因为JSONP是一种非标准行为,利用了script来做数据的事; 二是它使得别人能直接在他的网页上使用你的数据.
CORS:Cross-Origin Resource Sharing
简单请求
简单的GET和POST。
当developer.mozilla.org页面请求production.mozilla.org的api.
- 浏览器发出请求时,request里会带上Origin头,值为developer.mozilla.org
- 当api响应header里带的Access-Control-Allow-Origin字段包含(匹配)了发送请求的页面所在的域名(developer.mozilla.org),浏览器就会认为合法,把数据接着使用。
- 否则,浏览器会拦截掉这段数据:没错,响应的数据已经放body里到达了客户端,而浏览器会阻止掉,让专栏页面里负责发ajax的那段js代码拿不到响应值。
- 这样的好处很明显:我只需要在服务器端(网关比如nginx这一层)配置好Access-Control-Allow-Origin,从而使后端代码不需要写判断对请求域名进行处理(以前的确写过),就阻止其他人纯前端的手段这些后台数据, 完成了HTTP访问控制。
预检请求
PUT和DELETE等,或者请求时添加了CORS安全的header之外的header(如自定义的).
浏览器主动向目标api发出一个OPTIONS预检请求,这个请求里会带三个和跨域相关的header,其值为预检之后,正式发送api请求时将会使用的
- 来源/方法/请求头:
- Origin
- Access-Control-Request-Method
- Access-Control-Request-Headers 预检请求的响应需要带着与它们对应匹配的header和值,这样浏览器才会去请求跨域api。
带cookie的请求
要求响应头里Access-Control-Allow-Credentials为true,且Access-Control-Allow-Origin不能是通配符,防止后端犯错。
点击劫持
点击劫持—clickjacking
实现原理可以如下:
- 假如支付宝有一个页面,页面上的按钮点击是转账1000元给XXX
- 我把这个页面作为一个iframe放在a.com的网页上
- 我把这个iframe设置为透明,在它的按钮位置下面放置一个可以看见的「下一页」按钮
- 你看见我的网页,毫无防备地点击了下一页,实际上点击的位置是转账按钮
- 这种「跨域」也有类似CORS的控制方式,即
X-Frame-Options
响应头。它的值有三种:- DENY。表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
- SAMEORIGIN。表示该页面可以在相同域名页面的 frame 中展示。
- ALLOW-FROM uri。表示该页面可以在指定来源(uri)的 frame 中展示。
发现网页在iframe里,且X-Frame-Options响应头的值不符合要求,浏览器不会加载这个iframe。
附录
文章作者 zput
上次更新 2018-05-24