1、跨域请求

从本域名访问不同域名或端口的http请求统一称为跨域请求,为了安全起见,浏览器会阻止从脚本中(比如js、css)发起http跨域请求,但资源以嵌入的方式是可以加载的。

以下是可能嵌入跨源的资源的一些示例:

  • <script src="..."></script>标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。
  • <link rel="stylesheet" href="..."> 标签嵌入CSS。由于CSS的松散的语法规则, CSS的跨域需要一个设置正确的Content-Type消息头。不同浏览器有不同的限制:IE, Firefox, Chrome, Safari (跳至CVE-2010-0051)部分 和 Opera
  • <img>嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG,...
  • <video><audio>嵌入多媒体资源
  • <object>,<embed><applet>的插件
  • @font-face 引入的字体。一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)。
  • <frame> <iframe>载入的任何资源。站点可以使用`X-Frame-Options消息头来阻止这种形式的跨域交互。

非嵌入式http跨域请求分两种:

1、简单请求
简单请求需要满足三个条件:

  • 请求的methods仅限于GET、HEAD、POST
  • Content-Type头值必须为text/plain|multipart/form-data|application/x-www-form-urlencoded其中之一
  • 请求头部不可以添加额外的头部

此类请求只是简单的发送请求,是否能成功,需要服务器端配置Access-Control-Allow-Origin: yourDomain | *

2、预检请求
与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响
简单请求需要满足三个条件:

  • 请求的methods为PUT 、DELETE 、CONNECT 、OPTIONS 、TRACE 、PATCH中任一种HTTP方法
  • Content-Type头值不为text/plain|multipart/form-data|application/x-www-form-urlencoded其中之一
  • 请求头部添加了额外的头部

所谓预检请求,就是在正式请求发送之前,先发送一个OPTIONS请求去服务器询问服务器是否处理正式请求的method以及带的headers,如果处理,那就发送正式请求,否则报错 code 405。
比如发送一个跨域的get请求,但是添加了一个headers: {myheader: true}, 这样满足了预检请求的条件,浏览器拦截到该get请求后,检查到headers中有额外headers,那么就会自己先发一个OPTIONS请求,带上get请求的method与headers去访问服务器。

2、跨域请求需要带上cookie

当发送跨域请求时,有时需要带上cookie或者其他证书去认证,需要在前端请求headers中添加withCredentials:true,这样才会带上cookie,并且服务器端的响应中需携带 Access-Control-Allow-Credentials: true,否则浏览器将不会把响应内容返回给请求的发送者。

注意,对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“*”。
这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为http://yourhost.com,则请求将成功执行。
另外,响应首部中也携带了 Set-Cookie 字段,尝试对 Cookie 进行修改。如果操作失败,将会抛出异常。

参考:

1、浏览器的同源策略
2、HTTP访问控制(CORS)
3、前后端通讯系统
4、web font 字体跨域