同源策略与跨域
同源策略是一种限制来自于一个源的脚本和文档如何与另一个源的资源进行交互。
跨域网络请求
跨域控制两个不同源之间的交互,这些交互分为以下三类:
- 跨域写通常允许。如链接,重定向和表单提交。一些HTTP请求需要预检(preflight),预检请求首先通过OPTIONS方法发送一个HTTP请求到其他域的资源,为了确定实际的请求是否可以安全发送。
- 跨域嵌入(embedding)通常允许
- 跨域读通常不允许
跨域嵌入允许如下的资源嵌入:
- script标签,只有同源的语法错误才可以显示
<link rel="stylesheet" href="...">
标签- img标签
- video或者audio
- @font-face字体。一些浏览器允许跨域字体
- frame和iframe标签内容,可以使用X-Frame-Options头阻止跨域framing
如何实现跨域请求
使用CORS来允许跨域请求。CORS是HTTP的一部分用于让服务器指定哪一个主机被许可从服务器加载内容。
插个题外话,HTTP头中的Host字段,Origin字段以及Referer字段很类似,要做好区分。
- Host字段指明服务器域名(对于虚拟主机),和一个可选的端口号。
- Origin字段说明请求从哪里发起,包括协议和主机名,端口可选,类似于Referer,但不包含完整路径信息。常用于CORS.
- Referer告知服务器请求从哪个页面来的,url段也就是#以及用户信息
username:password
不包含在其中,可用于日志分析,访客识别等。也可用于csrf的防治。
通过设置access-control-allow-origin来实现跨域请求,值如果为*表示任意域都可以请求。我们也可以在服务端设置一个origin数组来表示我们允许访问我们服务器特定资源的域。express种cors中间件就是用于设置该行为的。
对于跨域请求,分为简单请求和复杂请求,简单请求有以下几种:
- 使用GET,POST,HEAD方法。
- Content-Type为以下三种,application/x-www-form-urlencoded,text/plain,multipart/form-data
不符合的一般就是复杂请求,复杂请求的CORS请求,在正是请求之前,会preflight也就是发起预检请求,该请求方法为OPTION,服务端来根据请求头内容来授予相应访问权限。这些逻辑都可以在后端进行控制,如使用cors中间件函数。