• ASP.NET WebAPI 15 CORS


    同源策略

    首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。

    对于同源必须要求URL在如下几个方面相同:

    1. 网络协议(http与https不同)
    2. 域名
    3. 端口(80与8080不同)

    JSONP

    JSONP是跨域访问的一种方法。在web开发中我们经常会引用第三方的js文件,这个时候我们会发现浏览器并没有拦截。JSONP就是利用向网页中添加script标签的方式去进行跨域访问。

    一般处理在处理JSONP的时候会将回调函数名与参数作为QueryString传给服务端,服务端再根据上传的函数名生成js回传给客户端。

    由于采用的是添加script标签的方式,所以JSONP只能通过GET方法访问服务器。另外由于服务端要根据上传的函数名生成js,所以JSONP方法得到的并不是数据,而是方法的调用。

    Demo中我写了一个JSONP的服务端生成与客户端调用方法。

    CORS

    对于CORSAccess-Control-Allow-Origin

    引用System.Web.Http.Cors

    通过NuGet管理添加System.Web.Http.Cors,我引用的库名为:Microsoft ASP.NET Web API 2.2 Cross-Origin Support

    引用库后,首先在WebApiConfig.Register方法中首行,添加一句 config.EnableCors()记得一定要添加到首行。开始我也是添加在末行,但一直运行不成功,花了好半天功夫,才找到是这个问题。这个以后有时间再看看Cors内部的实现原理,按说不应该出现这样的问题。)。

     

    public static void Register(HttpConfiguration config) 
    
     { 
    
    // Web API 配置和服务
    
    config.EnableCors(); 
    
    // Web API 路由
    
    config.MapHttpAttributeRoutes(); 
    
     
    
     config.Routes.MapHttpRoute( 
    
     name: "DefaultApi", 
    
     routeTemplate: "api/{controller}/{action}/{id}", 
    
     defaults: new { id = RouteParameter.Optional } 
    
    ); 
    
     } 
    

    System.Web.Http.Cors库对于Cors控制也是通过特性(Attribute)来实现的。System.Web.Http.Cors库提供了两个与Cors的特性:EnableCorsAttributeDisableCorsAttribute,这两个特性都是基于ControllerAction的。

     

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] 
    
    public sealed class DisableCorsAttribute : Attribute, ICorsPolicyProvider
    
     { 
    
    public DisableCorsAttribute(); 
    
    public Task<System.Web.Cors.CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken); 
    
     } 
    

     

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] 
    
    public sealed class EnableCorsAttribute : Attribute, ICorsPolicyProvider
    
     { 
    
    public EnableCorsAttribute(string origins, string headers, string methods); 
    
    public EnableCorsAttribute(string origins, string headers, string methods, string exposedHeaders); 
    
    public IList<string> ExposedHeaders { get; } 
    
    public IList<string> Headers { get; } 
    
    public IList<string> Methods { get; } 
    
    public IList<string> Origins { get; } 
    
    public long PreflightMaxAge { get; set; } 
    
    public bool SupportsCredentials { get; set; } 
    
     
    
    public Task<System.Web.Cors.CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken); 
    
     } 
    

    EnableCorsAttributeDisableCorsAttribute都实现了ICorsPolicyProvider接口。但 DisableCorsAttribute没有别的属性与构造函数,它的使用场景大致为当Controller已经被添加EnableCorsAttribute后,为个别不做CorsAction禁用掉。

    EnableCorsAttribute的与响应头部信息相对应,其对应关系如下:

    属性

    头部信息

    备注

    Origins

    Allow-Control-Allow-Origin

    CORS允许的请求域名,用逗号(,)去区他不同的域名,如:http://localhost:64299,http://www.baidu.com

    对于没有域名,可以用星号(*)

    Methods

    Allow-Control-Allow-Method

    CORS允许的请求方法,用法同Origins

    Headers

    Allow-Control-Allow-Headers

     

    ExposedHeaders

    Allow-Control-Expose-Header

     

    PreflightMaxAge

    Allow-Control-Max-Age

     

    SupportsCredentials

    Allow-Control-Allow-Credentials

     

    还是IE

    在测试过程中我发现在火狐上能够正常运行,但到了IE是就不行了,经过一番查找,发现要在要添加一句话:

    jQuery.support.cors = true;

    但加了这句话后,虽然/api/demo/GetFigureByCors可以调的,/api/demo/GetFigureNoCors也可以调用了。到这又郁闷了,这又是要搞那样。又经过一番折腾,才发现这个时候jQuery并不是用的XMLHttpRequest,而是采用的IE自带的XDomainRequest组件,并且该组件只支持IE8及以上。

    关于Demo

    Demo中出于对同源的规则的考虑,我定义了两个Web项目:API_15API_15.WebAPI_15中的DemoController分别定义的三个方法GetFigureByJsonPGetFigureNoCorsGetFigureByCors分别用于JSONP,非CorsCors调用。

     

    public class DemoController : ApiController
    
     { 
    
    public HttpResponseMessage GetFigureByJsonP(string callback) 
    
     { 
    
    StringBuilder result = new StringBuilder(); 
    
     
    
     result.Append("callback("); 
    
     result.Append(JsonConvert.SerializeObject(FigureManager.Figures)); 
    
     result.Append(")"); 
    
    return new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(result.ToString()) }; 
    
     } 
    
     
    
    public IEnumerable<Figure> GetFigureNoCors() 
    
     { 
    
    return FigureManager.Figures; 
    
     } 
    
     
    
    //[EnableCors(origins:"*",headers: "*",methods:"*")]
    
     [EnableCors(origins: "http://localhost:64299,http://www.baidu.com", headers: "GET,POST", methods: "*")] 
    
    public IEnumerable<Figure> GetFigureByCors() 
    
     { 
    
    return FigureManager.Figures; 
    
     } 
    
     }
    

    API_15.Web项目中只定义了一个页面,通过jQueryAJAX去调用API_15中三个Action

    源码

       

    Github: https://github.com/BarlowDu/WebAPI(API_15API_15.Web)

  • 相关阅读:
    使用Ruby On Rails建立一个山寨小说站(一)
    sql server 数据库备份概述
    JVM崩溃的原因及解决!
    C++中的字节对齐
    jqueyr用jsonp跨越,有服务器端代码(.net(C#语言))
    lammps_data文件
    jquery日历插件_时间范围_双日历_多日历
    js 判断所选时间(或者当前时间)是否在某一时间段
    webstorm安装时遇到The JVM could not be started的解决方法
    Webstorm快捷键
  • 原文地址:https://www.cnblogs.com/gangtianci/p/5027432.html
Copyright © 2020-2023  润新知