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内部的实现原理,按说不应该出现这样的问题。)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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的。

1
2
3
4
5
6
7
8
9
10
11
[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);
 
 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[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 { getset; }
 
public bool SupportsCredentials { getset; }
 
  
 
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调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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)

WebAPI 15 CORS的更多相关文章

  1. ASP.NET WebAPI 15 CORS

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

  2. WebApi开启CORS支持跨域POST

    概念:CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing).它允许浏览器向跨源服务器,发出XMLHttpRequest请求 ...

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

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

  4. WebApi使用cors配置跨域问题

    1.首先安装CORS,在WebApiCors项目上面使用Nuget搜索“microsoft.aspnet.webapi.cors”,安装第一个 2.当我们安装这个包之后,现有的packages目录下会 ...

  5. 让webapi支持CORS,可以跨域访问

    1.在NuGet里搜索webapi找到下面的扩展,添加进项目里. 2.在Global.asax中添加一行代码 protected void Application_Start() { //添加CORS ...

  6. webapi的cors配置

    NuGet搜索 cors,安装如图显示的: 一.全局配置 在App_Start文件夹的WebApiConfig.cs中加入代码 EnableCorsAttribute cors = new Enabl ...

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

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

  8. ASP.NET Web API 跨域访问(CORS)

    一.客户端用JSONP请求数据 如果你想用JSONP来获得跨域的数据,WebAPI本身是不支持javascript的callback的,它返回的JSON是这样的: {"YourSignatu ...

  9. Cors 跨域Access-Control-Allow-Origin

    1.Access-Control-Allow-Origin 指定格式 The Origin header field has the following syntax: origin = " ...

随机推荐

  1. WPF案例(-)模拟Windows7 Win+Tab切换

    原文:WPF案例(-)模拟Windows7 Win+Tab切换 一个使用Wpf模拟Windows7 Win+Tab页面切换的小程序,使用快捷键Ctrl+Down或Ctrl+Up在示例程序各个页面元素之 ...

  2. HDU 4940(杭电更多的学校#7 1006) Destroy Transportation system(到处乱混)

    职务地址:pid=4940">HDU 4940 当时这个题一看就看出来了是网络流的最小割.然后就一直在想建图. .然后突然发现,应该要让T集合的数目最少,不然仅仅要有两个,那这两个的每 ...

  3. 恢复gvim的ctl+v可视模式设置

    set nocompatiblesource $VIMRUNTIME/vimrc_example.vim"source $VIMRUNTIME/mswin.vim (注释此行)behave ...

  4. cocos2d-x 旅程開始--(实现瓦片地图中的碰撞检測)

    转眼隔了一天了,昨天搞了整整一下午加一晚上,楞是没搞定小坦克跟砖头的碰撞检測,带着个问题睡觉甚是难受啊!还好今天弄成功了.只是感觉程序不怎么稳定啊.并且发现自己写的东西让我重写一遍的话我肯定写不出来. ...

  5. JAVA 根据经纬度算出附近的正方形的四个角的经纬度

    /** * * @param longitude 经度 * @param latitude 纬度 * @param distance 范围(米) * @return */ public static ...

  6. ecshop 后台批量上传商品 完整上传

    ecshop 后台批量上传商品,之所以无法上传,是因为后台上传php文件方法中没有导入商品原图路径 将ecshop根目录中的admin/goods_batch.php文件全部修改为 <?php ...

  7. java.util.concurrent.ThreadPoolExecutor

    java.util.concurrent.ThreadPoolExecutor An ExecutorService that executes each submitted task using o ...

  8. win7问题解决,凭据管理器和无法访问,不允许一个用户使用一个以上用户名与服务器或共享资源进行多重连接。

    WIN7凭据管理器,如果你用一个帐号远程登录以后在电脑中会记住这个信息,假如你想用另外的帐号,那么就到控制面板-凭据管理器里中进行修改或者删除. 如果你登录以后提示,“无法访问.不允许一个用户使用一个 ...

  9. sitemap.xml

    内部类  在类内部的类 1.解决多继承 2.解决继承和实现接口时候方法名冲突情况 3.实现数据隐藏 只有内部类可以拥有4种访问修饰符 当内部类为private的时候,有外部类提供方法来访问内部类 常规 ...

  10. IOS开发-通知与消息机制

    在多数移动应用中不论什么时候都仅仅能有一个应用程序处于活跃状态.假设其它应用此刻发生了一些用户感兴趣的那么通过通知机制就能够告诉用户此时发生的事情. iOS中通知机制又叫消息机制,其包含两类:一类是本 ...