简析ASP.NET WebApi的跨域签名
之前的文章写了关于WebApi的跨域问题,当中的方法只是解决了简单请求的跨域问题而非简单请求的跨域问题则没有解决。
要弄清楚 CORS规范将哪些类型的跨域资源请求划分为简单请求的范畴,需要额外了解几个名称的含义,其中包括 “简单 (HTTP)方 法 (Simple Method) “、“简单(请求)报头 (Simple Hader)” 和 “ 自定义请求报头 (Author Request Header/ Custom Request Header)” 。
CORS规范将GET、HEAD、POST这三个HTTP方法视为“简单HTTP方法”,而将请求报头Accept、Accept-Language、Content-Language以及Content-Type采用Application/X-www-form-urlencoded、multipart/form-data、text/plain的报头称为简单请求报头。
简而言之,简单请求就是只包含简单请求报头的采用简单方法的Http请求,其他的请求即为费简单请求,如本文提到的跨域签名所需要的签名参数就是添加在HTTP请求的自定义头部里面(如果把签名信息包含在处理函数的参数里面就显得接口签名做的很LOW)。
  跨域其实说的是浏览器的同源策略对JavaScript脚本的Ajax请求的一些限制,阻止程序对脚本请求的数据的操作,而不是阻止请求的发送以及数据的接收,如果用抓包工具查看网络数据的话,其实可以很明显的看到请求的发送,以及接口正常的数据返回。但是为什么浏览器不能正常的处理数据呢?这是因为浏览器需要得到资源提供者的授权之后才会把资源分发给消费者(即JavaScript脚本),而Ajax在进行跨域资源的请求的时候会在报头添加一个“Origin”头部,这个头部的值就是当前发起请求的域。因此想要解决简单请求的跨域问题只需要对请求报文中的Origin的值进行处理,对已授权的域的响应添加一个响应报头"Access-Control-Allow-Origin",一般对授权域的响应报头"Access-Control-Allow-Origin"值置为“*”。而非简单请求的跨域调用流程就跟简单报文的调用流程有所差异呢,在发送非简单报文时,浏览器就会采用“预检”机制来完成非简单请求的跨域资源请求。所谓预检机制就是浏览器在发送真正的跨域资源请求前 ,先发送一个预检请求(PreflightRequest)。 预检请求为一个采用 0PTIONS方法的请求,这是一个不包含主体的请求,用户凭证相关的报头也会被剔除。基于真正资源请求的一些辅助授权的信息会包含在此预检请求的响应报头中。 除了代表请求页面所在站点的 “Origin” 报头之外,如 下所示的是两个典型的请求报头 。
● Access-Control-Request-Method:跨域资源请求采用的HTTP方 法 。
● Access-Control-Request-Headers:跨域资源请求携带的自定义报头列表 。
资源的提供者在接收到预检请求之后会根据其提供的相关报头进行授权检验 ,具体的检验逻辑包括确定请求站点是否值得信任 ,以及请求采用HTTP方法和自定义报头是否被允许 。如果预检请求没有通过授权检验 ,资源提供者一般会返回一个状态为“400,Bad Reuqest”的响应(也可自定义返回报文消息,如本文) 。 反之则会返回一个状态为 “200,OK” 的响应(也可自定义返回报文消息) ,授权相关信息会包含在响应报头中。
除了上面介绍的 “Access-Control-Allow-Origin” 和 “Access-Control-Allow-Method” 报头之外,预检请求的响应还具有如下 3个典型的报头。
● Access-Control-Allow-Method:跨域资源请求允许采用 的 HTTP方法列表 。
● Access-Control-Allow-Headers:跨域资源请求允许携带的自定义报头列表 。
● Access-Control-Max-Age:浏览器可以将响应结果进行缓存的时间 (单位为秒 ),这样可以让浏览器避免频繁地发送预检请求 。
如果预检请求满足如下三个条件,浏览器则认为后续将要发送的跨域资源请求是被授权的
● 通过请求的 “Origin” 报头表示的源站点必须存在于 “Access-Control-Allow-Origin”响应报头标识的站点列表中。
●预检请求的 “Access-Control-Request-Headers” 报头存储的报头名称均在响应报头“Access-Control-Allow-Headers” 表示的报头列表之内。
●预检请求的“Access-Control-Request-Method” 报头表示的请求方法在预检请求响应报文“Access-Control-Allow-Methods”表示的列表之内。
因此以上可知:想要完成非简单报文的跨域请求,就必须要在服务器端对预检请求进行正常的应答,当收到预检请求时,对其进行正常的响应,这就需要在应答报文中添加“Access-Control-Allow-Origin”、“Access-Control-Allow-Methods”、“Access-Control-Allow-Headers”,这三个自定义报文头,同时这三个报文头要按照预检机制的要求进行填充。尤其是“Access-Control-Allow-Headers”自定义头部列表要包含签名所需的所有自定义头部名。
以上便是对跨域、预检机制以及其解决方法的描述,接下来讲实际的处理方法
(1)跨域支持:对控制器添加一个Filter属性并重写OnActionExecuted方法,向响应报文添加自定义头部。
(2)预检报文应答:因为一般的API控制器都没有实现OPTIONS方法,而预检报文的请求方法是OPTIONS,因此需要我们实现OPTION方法。至于每个控制器多了一个平时都不使用的OPTIONS方法,写在那里难看,这就是系统架构要考虑的问题了,这里我们只说具体问题的具体解决方法。
(3)接口签名验证:对控制器添加一个Filter属性对自定义报文进行自己的验证逻辑,这个就随意发挥了。
跨域的预检报文支持代码:
/// <summary>
/// 添加跨域支持
/// </summary>
public class EnableCors : ActionFilterAttribute
{
/// <summary>
/// 操作标记
/// </summary>
private bool Flag { get; set; } /// <summary>
/// 默认构造函数 true:开启跨域 false:关闭跨域支持
/// </summary>
/// <param name="para"></param>
public EnableCors(bool para)
{
Flag = para;
} /// <summary>
/// 方法执行之后执行
/// </summary>
/// <param name="actionExecutedContext"></param>
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
if (Flag != true) return;
if (actionExecutedContext.Response == null) return;
if (actionExecutedContext.Response.Headers.Contains("Access-Control-Allow-Origin"))
{
actionExecutedContext.Response.Headers.Remove("Access-Control-Allow-Origin");
}
if (actionExecutedContext.Response.Headers.Contains("Access-Control-Allow-Method"))
{
actionExecutedContext.Response.Headers.Remove("Access-Control-Allow-Method");
}
if (actionExecutedContext.Response.Headers.Contains("Access-Control-Allow-Headers"))
{
actionExecutedContext.Response.Headers.Remove("Access-Control-Allow-Headers");
}
actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type,TimeStamp,Parameter,RandNum");
}
}
接口签名代码:
/// <summary>
/// 接口签名属性
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ApiAuthorization : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
base.OnAuthorization(actionContext);
if (actionContext.Request.Method == HttpMethod.Options) return;//支持跨域的自定义报头请求(预检机制)
//TODO这里就是接口签名的代码,可以取自定义头部进行处理,签名通过则直接return,否则对actionContext.Response进行赋值,表示签名失败后面的操作不执行
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden, new CheckResult() { Result = false, Message = "Access denied!" });
}
}
/// <summary>
/// 基础控制器
/// </summary>
[DataType(ApiDataType.Json)]
[EnableCors(true)]
[Description("Api基础控制器")]
[ApiAuthorization]
public class ApiBaseController : ApiController
{
/// <summary>
/// 为了支持ajax跨域的预检机制
/// </summary>
public void Options()
{
}
}
通过以上步骤就完成了跨域的预检报文应答,接口签名。实际运行效果如下图所示:
首先我发送一个非简单报文的操作,我通过Fiddler实际抓到了两个包,第一个就是上面所说的预检报文,第二个才是包含我们所有自定义报文头部的实现我们真正跨域资源请求的报文。

而预检请求报文以及应答报文的信息如图(格式也如上文所讲):

跨域资源请求报文及其应答报文如下(注意我们用于接口签名的自定义报文头):

下面来一个正常通过跨域操作,并且签名验证失败的报文,同样是一个预检报文,一个正式报文

简析ASP.NET WebApi的跨域签名的更多相关文章
- ASP.NET WebAPI解决跨域问题
		
跨域是个很蛋疼的问题...随笔记录一下... 一.安装nuget包:Microsoft.AspNet.WebApi.Core 二.在Application_Start方法中启用跨域 1 protect ...
 - 为Asp.net WebApi 添加跨域支持
		
Nuget安装包:microsoft.aspnet.webapi.cors 原文地址:https://www.asp.net/web-api/overview/security/enabling-cr ...
 - asp.net webapi支持跨域
		
1.Install-Package Microsoft.AspNet.WebApi.Cors 2. using System.Web.Http; namespace WebService { ...
 - asp.net core webapi之跨域(Cors)访问
		
这里说的跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作 ...
 - 关于WebService、WebApi的跨域问题
		
随着移动互联网的发展, 传统营销模式往网站以及移动客户端转移已经成为一种趋势.接触过互联网开发的开发者肯定会很熟悉两种网络服务WebApi.WebService.在使用JavaScript进行数据交互 ...
 - .NET压缩图片保存  .NET CORE WebApi Post跨域提交  C# Debug和release判断用法  tofixed方法 四舍五入  (function($){})(jQuery);  使用VUE+iView+.Net Core上传图片
		
.NET压缩图片保存 需求: 需要将用户后买的图片批量下载打包压缩,并且分不同的文件夹(因:购买了多个用户的图片情况) 文章中用到了一个第三方的类库,Nuget下载 SharpZipLib 目前用 ...
 - ASP.NET中Cookie跨域的问题及解决代码
		
ASP.NET中Cookie跨域的问题及解决代码 http://www.liyumei.net.cn/post/share18.html Cookies揭秘 http://www.cnblogs.c ...
 - asp.net core webapi Session 跨域
		
在ajax 请求是也要加相应的东西 $.ajax({ url:url, //加上这句话 xhrFields: { withCredentials: true } success:function(re ...
 - asp.net core webapi 配置跨域处理
		
在Startup.cs文件中的ConfigureServices方法中加入如下代码: //配置跨域处理 services.AddCors(options => { options.AddPoli ...
 
随机推荐
- js正则表达式详解及示例讲解
			
所谓正则表达式,简单来说就是一种规则,一种计算机能读懂的规则.js中的正则表达式语法是Perl5(一种很早的编程语言)的正则语法的子集.本文将在基础知识的基础上添加示例帮助快速理解正则表达式. 学习正 ...
 - iOS开发之Block
			
1.定义 (1) Block是OC中的一种数据类型,在iOS开发中被广泛使用 (2) ^是Block的特有标记 (3) Block的实现代码包含在{}之间 (4) 大多情况下,以内联inline函数的 ...
 - (转)关闭iptables和SELinux
			
1. 关闭SELinux setenforce 0 #临时关闭 编辑/etc/selinux/config,找到SELINUX 行修改成为:SELINUX=disabled: #永久关闭, ...
 - javascript 类型的判断
			
在平常写js代码,类型判断必不可少,那么我们常见有哪几种?看到了标题,先不看你会想到那些方法 ,常用呢些呢?那么今天我自己总结一些判断类型的判断,如有错,万望告知! 1:typeof 常用这种方法不错 ...
 - JQ实战一之烟花
			
本次的效果大概为当用户点击网页时,网页下方弹出一个类似烟花的长条条,然后在桌面上散开以达成类似烟花的特效.话不多说先上图. 首先布局,布局很简单 <style> body { backgr ...
 - html实现 页面禁止右键 禁止复制 禁止图片拖动 禁止复制和剪切
			
众所周知,一般的屏蔽的方法是用JS来编写的脚本,但是也可以直接通过修改网页属性的方法来屏蔽右键 禁止复制. 禁止右键 oncontextmenu="return false" 禁止 ...
 - Zookeeper3.4.9分布式集群安装
			
一.依赖文件安装 1.1 JDK 参见博文:http://www.cnblogs.com/liugh/p/6623530.html 二.文件准备 2.1 文件名称 zookeeper-3.4.9.ta ...
 - sublimeText3插件安装
			
1,官方下载sublimeText 3(百度搜索) 2,安装成功后按Ctrl+`调出console 3,然后输入 import urllib.request,os; pf = 'Package Con ...
 - WebService基础学习(三)—CXF
			
一.什么是CXF? Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF.Apache ...
 - ggplot2:分面的介绍
			
1.分面 分面是指在一个页面上自动摆放多幅图形的技巧,也就是说可以让不同分类的图同时展示在一张图上,这样方便于数据之间的的比较.ggplot2提供了网格型(facet_grid)和封装型(facet_ ...