• 同源策略与CORS


    同源策略

    同源策略是浏览器保护用户安全上网的重要措施,协议、域名、端口号三者相同即为同源。

    不同源下,浏览器不允许js操作Cookie、LocalStorage、DOM等数据或页面元素,也不允许发送ajax请求,同源下则不受影响。

    下图是在Chrom控制台中发送ajax跨域请求的报错信息:

     

    图片中黄色部分提示响应被阻止,说明在跨域的情况下,请求依然发送到了服务器且服务器返回了数据,只是被浏览器拦下了。

    对于跨域问题可以使用CORS来解决,使用CORS时,HTTP请求分为两种情况:简单请求与复杂请求。

    简单请求

    满足以下三点即为简单请求:

    • HTTP请求方法为GET、POST或HEAD
    • HTTP请求头只能包含Accept, Accept-Language, Content-Language, Content-TypeLast-Event-ID
    • ContentType的值只能为以下三种:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

    复杂请求

    除简单请求之外即为复杂请求。浏览器在发送复杂请求前会先发送Preflight request(预检请求),即发送OPTIONS请求。注意是浏览器发送的,用户无感。

     
     

    预检请求头包含两个特定字段:

    • Access-Control-Request-Method
      表示后续请求会用到的HTTP方法,该字段必选
    • Access-Control-Request-Headers
      后续请求中所设置的请求头部信息,注意,这里不包含浏览器默认设置的头部字段,如:User-Agent。该字段可不发送。

    服务器会检查对预检请求中的OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段值,并返回正常的HTTP响应。
    浏览器根据返回信息判断后续请求是否符合服务器端跨域要求,不符合则抛出错误信息。通过预检请求后,则发送后续请求,此时和简单请求无差别。

    服务器配置CORS的几个字段

    • Access-Control-Allow-Origin
      必选,设置允许哪些源访问服务器资源
    • Access-Control-Allow-Methods
      必选,设置允许哪些HTTP方法
    • Access-Control-Request-Headers
      设置HTTP请求头中包含哪些字段,如果浏览器请求包括Access-Control-Request-Headers字段,则必选

    以上三个字段为常用字段,其余字段配置参考:CORS policy options

    withCredentials与Cookie的跨域问题

    Cookie受到同源策略的限制没有那么严格,默认情况下,只要发送请求方所在域与Cookie的Domain值相同即可将cookie发送至服务器端,无需考虑协议和端口号。在默认情况下,客户端发起的HTTP请求会带上目标域的Cookie,但无法携带其它属于其它的域Cookie。

    我们可以借助XMLHttpRequest对象的withCredentials属性及CORS的Access-Control-Allow-Credentials二者来实现跨域的Cookie发送和写入。

    var xhr=new XMLHttpRequest();
    xhr.open('GET','http://www.target.com:8093/api/GetAllProductType');
    xhr.onreadystatechange=function(){
        if(xhr.readyState==4 && xhr.status==200){
            console.log(xhr.response);
        }
    }
    // 这里使用withCredentials属性来发送Cookie
    xhr.withCredentials=true;
    xhr.send();

    注意,在使用withCredentials时,服务器端不能将Access-Control-Allow-Origin的值配置为*,否则客户端会报错:

    Access to XMLHttpRequest at ''http://www.target.com:8093/api/GetAllProductType' from origin 'http://www.request.com:8094' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

    一个问题

    上周在ASP.NET Web API 2中使用CORS,报错:The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed。原因是服务器端配置了两次CORS,导致返回了两个Access-Control-Allow-Origin:*但浏览器只允许一个。

    经过排查发现在Web.config文件中也配置了CORS,与代码中的配置重复,注释掉之后问题解决。该问题参考了:stackoverflow上的回答。

    小结

    同源策略是浏览器为保障用户(数据)安全而对JS功能进行一定限制。毕竟HTML与CSS只负责网页结构与样式,不具备操作页面元素及与服务器交互的功能。

    离开浏览器环境后跨域问题也就不复存在。

    严格的限制会导致一些不便,故同源策略开了几个口子:

    • Cookie共享
      子域名可以共享父级域名的cookie

    • 嵌入式资源获取
      <script>,<img>,<link>等标签获取资源不受同源策略限制,这也是JSONP实现跨域的原理

    常用处理跨域请求的方式有JSONP和CORS:

    • JSONP
      需要前后端协作处理且只支持GET请求
      不是标准规范
      对老式浏览器友好(这里想到了老古董IE:)

    • CORS
      支持GET、POST、PUT、DELETE等多种请求
      服务器端配置简单且不需要前端写额外的代码
      目前主流浏览器均支持CORS规范

    推荐阅读

    浏览器家族的安全反击战

    Enable Cross-Origin Requests (CORS) in ASP.NET Core

    前后端分离 | 关于登录状态那些事

    Cross-Origin Resource Sharing (CORS)

    Cookie中的几个概念

  • 相关阅读:
    Asp.net MVC 3实例学习之ExtShop(三)——完成首页
    Asp.net MVC 3实例学习之ExtShop(一)————创建应用并设置开发环境
    JDK里的设计模式
    Linux系统下ssh的相关配置
    简单介绍asp模式与saas模式
    Linux系统中xorg.conf文件简介
    [C++] MurmurHash2的性能
    [C++] 在程序里调用DOS命令
    Android SDK 1.5中文版 (Application基础—1)
    linux系统单网卡绑定双IP的方法
  • 原文地址:https://www.cnblogs.com/Cwj-XFH/p/9785337.html
Copyright © 2020-2023  润新知