zoukankan      html  css  js  c++  java
  • 同源策略与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中的几个概念

  • 相关阅读:
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Visual Studio断点调试, 无法监视变量, 提示无法计算表达式
    ASP.NET MVC中MaxLength特性设置无效
    项目从.NET 4.5迁移到.NET 4.0遇到的问题
    发布网站时应该把debug设置false
    什么时候用var关键字
    扩展方法略好于帮助方法
    在基类构造器中调用虚方法需谨慎
    ASP.NET MVC中商品模块小样
    ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现
  • 原文地址:https://www.cnblogs.com/Cwj-XFH/p/9785337.html
Copyright © 2011-2022 走看看