跨源
跨源
什么是跨源(跨域)
严格来说,跨域说法只是跨源的一种。跨源:代表js代码请求一些不同源的资源这样的行为
同源策略
从一个源访问不同协议、域名、端口的另一个源的资源时,浏览器会触发的一种保护机制,阻止跨源的一些行为
但父域名和子域名之间不是跨源的,比如abc.example.com和example.com
跨源行为
- 跨源写操作:
POST、DELETE、PUT、PATCH这些会修改服务器数据的操作,使用window、location等修改url的api,重定向等,都是允许的 - 跨源资源嵌入:
<img>、<video>、<embed>、<script>、<link>、@font-face、<ifream>这些标签访问一些资源 - 跨源读操作:
GET、HEAD(一般都是不允许的,会被浏览器阻拦)
PS. 第一第二种行为一般浏览器都是放行的,允许的。第一二种是浏览器发起的GET请求,后面一种行为一般不允许
CORS (Cross-Origin Resource Sharing) 跨源资源共享
解决XHR、FETCH跨域的一种方法,得前端和后端一块设置。允许服务器通过一系列的HTTP头来标识当前的浏览器请求是否允许跨源
注意,针对的是HTTP请求
针对不同的跨源HTTP请求有不同的CORS解决方法,把跨源请求分成两种
简单请求
满足下面条件的请求
HEAD、GET、POST的表单提交- 请求头:
Accept、Accept-Language、Content-Language、Range、Content-TypeContent-Type仅限以下三种text/plainmultipart/form-dataapplication/x-www-form-urlencoded
- 请求中的任意
XMLHttpRequestUpload对象均没有注册任何事件监听器;XMLHttpRequestUpload对象可以使用XMLHttpRequest.upload属性访问 - 请求中没有使用
ReadableStream对象
简单请求通常在发送时浏览器会自动添加Origin头,服务器要返回Access-Control-Allow-Origin头,一般这个头配置可以跨源的域,或通配符*(一般开发时候用)
复杂请求
不满足上述请求的其他请求,其实区分也挺容易,就看是否有非简单请求的方法、是否添加了一些其他的请求头(或自定义请求头)
预检请求
OPTIONS请求,前端发送复杂请求前,需要先发送预检请求,询问服务器允许的请求头Access-Control-Request-Headers,请求方法Access-Control-Request-Method(这俩请求头都是预检请求专用的,其他请求则会在发送跨源时自动添加一些诸如Origin等的请求头),后端会返回响应(预检请求的响应不包含响应体204),包含对应头(也有不返回的情况)、cookie等
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Max-Age
简单请求往往都是跨源内嵌资源请求,或者是一些简单的表单提交发出的。对于简单的表单提交,如果是跨源的表单提交服务器不会返回响应。不返回响应不代表不能在前端发送这些请求,而且这些请求服务器很可能已经是收到了的
CSRF攻击 (跨站请求伪造攻击)
如果没有预检请求(这里指任何请求不受跨源限制),就可以发送诸如DELETE请求删除服务器上的用户数据。服务器得处理很多非法跨源请求
有预检请求,会事先和服务器商量好,达成约定。只能发送哪些方法,哪些源可以发送,是否携带凭证等
下面是开发中使用一些工具、技巧解决跨源问题
vue解决跨源问题
- http-proxy
- vite、nuxt自带代理模块,用时配置。内置了http-proxy
- nginx等(生产环境)
react解决跨源问题
- http-proxy-middleware
- nginx等(生产环境)
都是设置了本地代理服务,相当于弄了一个同源环境的后端应用等,直接去掉了限制
JSONP
概念
JSONP(JSON with Padding)利用script标签的src属性没有跨源限制来完成GET请求
优点
- 兼容性好,古老浏览器都支持
缺点
只能发送
GET请求前端和后端代码耦合,需要后端调用前端传的回调函数
后端代码也得是js
<script type='text/javascript'> |
在script标签中,传递了cb参数,参数的值为上面定义的回调函数jsonpCallback
const Koa = require('koa'); |
从ctx中拿到对应的参数,调用前端传递的这个函数,这个函数中传递后端需要给前端发送的数据