同源策略

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

对于同源必须要求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的特性:EnableCorsAttribute与DisableCorsAttribute,这两个特性都是基于Controller与Action的。

[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); 

 }

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

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_15与API_15.Web。API_15中的DemoController分别定义的三个方法GetFigureByJsonP,GetFigureNoCors,GetFigureByCors分别用于JSONP,非Cors,Cors调用。

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项目中只定义了一个页面,通过jQuery的AJAX去调用API_15中三个Action。

源码

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

ASP.NET WebAPI 15 CORS的更多相关文章

  1. WebAPI 15 CORS

    WebAPI 15 CORS 同源策略 首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 对于同源必须要求URL在如下几个方 ...

  2. Asp.Net WebApi 启用CORS跨域访问指定多个域名

    1.后台action指定 EnableCors指定可访问的域名多个,使用逗号隔开 //支持客户端凭据提交,指定多个域名,使用逗号隔开 [EnableCors("http://localhos ...

  3. Asp.Net WebApi+Microsoft.AspNet.WebApi.Core 启用CORS跨域访问

    WebApi中启用CORS跨域访问 1.安装 Nugget包Microsoft.AspNet.WebApi.Cors This package contains the components to e ...

  4. Asp.Net WebApi 项目及依赖整理

    一.目前版本 Microsoft ASP.NET Web API 2.2 对应程序集版本5.2.3 二.默认生成的配置文件中的内容 <packages> <package id=&q ...

  5. 连表查询都用Left Join吧 以Windows服务方式运行.NET Core程序 HTTP和HTTPS的区别 ASP.NET SignalR介绍 asp.net—WebApi跨域 asp.net—自定义轻量级ORM C#之23中设计模式

    连表查询都用Left Join吧   最近看同事的代码,SQL连表查询的时候很多时候用的是Inner Join,而我觉得对我们的业务而言,99.9%都应该使用Left Join(还有0.1%我不知道在 ...

  6. Enable Cross-Origin Requests in Asp.Net WebApi 2[Reprint]

    Browser security prevents a web page from making AJAX requests to another domain. This restriction i ...

  7. 为Asp.net WebApi 添加跨域支持

    Nuget安装包:microsoft.aspnet.webapi.cors 原文地址:https://www.asp.net/web-api/overview/security/enabling-cr ...

  8. 【开源】分享一个前后端分离方案-前端angularjs+requirejs+dhtmlx 后端asp.net webapi

    一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年a ...

  9. ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver

    ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver   Message WebAPI作为通信架构必定包含包含请求与响应两个方法 ...

随机推荐

  1. 我的首个MOOC课程《面向对象软件开发实践》

    我的首个MOOC课程<面向对象软件开发实践> 我将在网易云课堂开讲MOOC课<面向对象软件开发实践>(http://mooc.study.163.com/course/YOOK ...

  2. 初探Stage3D(三) 深入研究透视投影矩阵

    关于本文 本文主要讲解从数学的角度如何推导出Stage3D中用到的两个投影矩阵 perspectiveLH public function perspectiveLH(width:Number,hei ...

  3. CSS基础(七):z-index详解

    概念 z-index 属性设置元素的堆叠顺序.拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面. 层级关系的比较 1. 对于同级元素,默认(或position:static)情况下文档流后面的 ...

  4. Vim安装jedi-vim提示的一个错误

    (仅为了提醒自己) 第一次的安装方法好像是通过 bundle安装的,好像是通过这个安装的并不是最新的版本,然后删除了通过下面的方法,最重要的是要执行 git submodule update --in ...

  5. 误删dpkg的/var/lib/dpkg/info文件夹的解决办法 zhuan

         今天安装软件时时,出现这样的错误提示:E: Sub-process /usr/bin/dpkg returned an error code (1)   上网查解决方案,被网上误导,一不小心 ...

  6. 十一、EnterpriseFrameWork框架的分层与系统业务的结合

    上章详细讲了EnterpriseFrameWork框架中的每个分层,这都是从技术层面来说明,也就是我们知道怎么来建一个控制器或一个业务对象,但开发过程中应该建一个什么样的控制器或业务对象了?本章的主要 ...

  7. Android Studio NDK 学习之接受Java传入的字符串

    本博客是基于Android Studio 1.3 preview版本,且默认你已经安装了Android SDK, Android NDK. 用Android Studio新建一个工程叫Prompt,其 ...

  8. 单链表List的C实现

    头文件———————————————————————————————— //单链表的实现 #ifndef _LIST_H_ #define _LIST_H_ #include <stdlib.h ...

  9. ruby -- 进阶学习(十六)ckeditor去除“浏览服务器”按钮

     FROM:http://blog.163.com/zjc_8886/blog/static/2408175201011222590967/ 实现方法: 由于ckeditor中的"上传图片& ...

  10. [SLAM] Studying Guidance

    Books from Zhihu: 幽默一把 看完Gonzalez:嗯,好像很好玩的样子,我也来搞一搞.看完Price:什么鬼,怎么这么多公式,公式看不懂肿么破.看完Szeliski:原来用一千页的书 ...