最近接手了App服務(wù)器重構(gòu)的工作漆魔,已經(jīng)N久沒有寫.net程序的我也要試著把以前的東西一點(diǎn)一點(diǎn)撿回來蝶溶。目前使用的技術(shù)是web api2诡蜓,這是一個類似與aps.net MVC的東西捺球,可以說其實(shí)就是一個東西,它相比于MVC垢乙,應(yīng)該可以叫MC,因?yàn)樗鼪]有視圖语卤,是一個純接口類型的項(xiàng)目追逮,這樣用來做后臺服務(wù)器的接口再好不過了。
想到很久以前粹舵,剛剛開始學(xué)習(xí)編程钮孵,做一個權(quán)限管理和驗(yàn)證,使用最笨的方法齐婴,需要在每個方法里面寫上驗(yàn)證的代碼油猫,判斷用戶的權(quán)限,這種代碼的冗余問題非常嚴(yán)重柠偶,到后來了解了<code>AOP面向切面</code>編程情妖,才知道原來還可以有過濾器這個東西睬关,正在被廣泛使用在<code>權(quán)限控制</code>,<code>身份驗(yàn)證</code>毡证,<code>日志記錄</code>等等很多用途上电爹。
ASP.NET Web API 特性
ASP.NET Web API 包含下列特性:
<font style='font-size:24px'>1.先進(jìn)的 HTTP 編程模型:</font> 使用新的強(qiáng)類型的 HTTP 對象模型直接操作 HTTP 請求和響應(yīng), 在 HTTP客戶端使用相同的編程模型和 HTTP 管道料睛;
<font style='font-size:24px'>2.支持路由:</font> Web API 完整支持 ASP.NET 路由丐箩, 包括路由參數(shù)和約束。 此外恤煞, 到動作的映射支持約定屎勘, 從此將不再需要向類或者方法添加類似于 [HttpPost] 之類的屬性;
<font style='font-size:24px'>3.內(nèi)容協(xié)商:</font> 客戶端與服務(wù)端可以一起決定 API 返回數(shù)據(jù)的格式居扒。 默認(rèn)支持 XML概漱, JSON 以及 Form URL-Encoded 格式, 可以擴(kuò)展添加自定義格式喜喂, 甚至可以替換掉默認(rèn)的內(nèi)容協(xié)商策略瓤摧;
<font style='font-size:24px'>4.模型綁定與驗(yàn)證:</font> 模型綁定器可以輕易地從 HTTP 請求中提取數(shù)據(jù)并轉(zhuǎn)換成在動作方法中使用的 .Net 對象;
<code><font style='font-size:24px'>5.過濾:</font> Web API 支持過濾玉吁, 包括總所周知的 [Authorize] 過濾標(biāo)記照弥, 可以為 Action 添加并插入自定義過濾, 實(shí)現(xiàn)認(rèn)證进副、異常處理等这揣;</code>
<font style='font-size:24px'>6.查詢聚合:</font> 只要簡單的返回 Iqueryable<T> , Web API 將會支持通過 OData 地址約定進(jìn)行查詢影斑;
<font style='font-size:24px'>7.改進(jìn)的 Http 細(xì)節(jié)可測試性:</font> Web API 不是將 HTTP 細(xì)節(jié)設(shè)置到一個靜態(tài)的 Context 對象上曾沈, 而是使用 HttpRequestMessage 和 HttpResponseMessage 實(shí)例, 可以使用這些對象的泛型版本為這些 Http 類型添加自定義類型鸥昏;
<font style='font-size:24px'>8.改進(jìn)的依賴反轉(zhuǎn) (IoC) 支持:</font> Web API 使用 MVC Dependency Resolver 實(shí)現(xiàn)的服務(wù)定位器模式在不同的場景下來獲取實(shí)例塞俱;
<font style='font-size:24px'>9.基于代碼的配置:</font> Web API 單獨(dú)使用代碼完成配置, 從而保證了配置文件的整潔吏垮;
<font style='font-size:24px'>10.自托管 (Self-Host) :</font> Web API 除了可以托管在 IIS 中障涯, 還可以托管在進(jìn)程中,依舊可以使用路由以及其它的特性膳汪。
從上面的介紹中可以看出wei api可以通過<code>標(biāo)記/特性</code>唯蝶,使用過濾器的方式來進(jìn)行深入到方法的操作,這樣做的好處是:便捷遗嗽,非常的便捷粘我,就讓我們來看看吧~
1、新建一個asp.net web的工程
2、選擇Empty 勾上web api
3征字、一個建好的空的web api項(xiàng)目
4都弹、新建一個控制器
TestController
<pre><code class='cs hljs'>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Results;
namespace Api.Controllers
{
public class TestController : ApiController
{
/// <summary>
/// 接收數(shù)據(jù)類型
/// </summary>
public class MyData
{
public string myname { get; set; }
public string myvalue { get; set; }
}
/// <summary>
/// 測試Action 進(jìn)行權(quán)限驗(yàn)證
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
[SecurityFilter("test")]
[HttpPost]
public JsonResult<string> test([FromBody] MyData data )
{
return Json("123121=====>"+data.myname);
}
/// <summary>
/// 權(quán)限不夠執(zhí)行的Action
/// </summary>
/// <returns></returns>
[HttpGet]
public JsonResult<string> error()
{
return Json("error");
}
}
}
</code></pre>
SecurityFilter(過濾器),繼承ActionFilterAttribute匙姜,實(shí)現(xiàn)OnActionExecuting方法畅厢,這個方法為Action執(zhí)行前執(zhí)行的方法,我就在這里來做權(quán)限驗(yàn)證的事情
<pre><code class = "cs hljs">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.Results;
using System.Web.Routing;
namespace Api.Filter
{
public class SecurityFilter: ActionFilterAttribute
{
private string name;
public SecurityFilter(){}
public SecurityFilter(string name) {
this.name = name;
}
/// <summary>
/// Action執(zhí)行前
/// </summary>
/// <param name="actionContext"></param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
//獲取request的參數(shù)列表【獲取API的參數(shù)】
// Dictionary<string, object> actionargument = actionContext.ActionArguments;
//找出請求參數(shù)
// RequestBaseEntity requestData = actionargument["requestData"] as RequestBaseEntity;
//requestData是參數(shù)的名字
//直接從上下文中回去請求參數(shù)氮昧,這個方法在HttpContext.Current.Request將無法獲取到
//獲取請求信息中的token和用戶信息
string myname = HttpContext.Current.Request["myname"].ToString();
Console.WriteLine(myname);
//現(xiàn)在用戶token信息是否有效和過期
if (!myname.Equals("tmm"))
{
//如果token已經(jīng)失效框杜,重定向至token過期返回頁面
HttpContext.Current.Response.Redirect("~/api/test/error");
//創(chuàng)建響應(yīng)對象,初始化為成功袖肥,沒有指定的話本次請求將不會被攔截
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
}
}
}
}
</code></pre>
為了模擬在項(xiàng)目中使用的post請求咪辱,于是我寫個簡單的html頁面,使用表單來提交post請求
我們先運(yùn)行項(xiàng)目(報錯不用管椎组,沒有設(shè)置默認(rèn)的路徑)

然后打開這個頁面梧乘,這個頁面的表單提交的路徑為運(yùn)行項(xiàng)目的test Action路徑。

這個時候直接提交庐杨,會被重定向到error的Action,放回的結(jié)果為error Action的放回結(jié)果
這是返回上個頁面夹供,在myname的文本框中輸入tmm灵份,這個是權(quán)限驗(yàn)證的規(guī)則,只有myname的值為tmm的時候哮洽,才不會對請求進(jìn)行攔截填渠,當(dāng)然在實(shí)際的項(xiàng)目開發(fā)中肯定是更換為去用戶的ID去數(shù)據(jù)庫進(jìn)行查詢來驗(yàn)證用戶是否有權(quán)限做這個事情。
這個時候再提交鸟辅,可以看到就能狗進(jìn)入test/test這個頁面了氛什。
再回過來看代碼,我們只需要在Action上面加上這個特性就能進(jìn)行過濾攔截匪凉,使用起來非常的方便枪眉,如果我們要對整個Controller進(jìn)行權(quán)限過濾,哪就可以將這個特性直接加在Controller的類名上面就行了再层,當(dāng)然也有特殊的情況贸铜,比如整個控制器中我大部分都要過濾,只有幾個不要過濾聂受,這樣好像僅僅這樣還是做不到可以有選擇性的過濾蒿秦,這個時候我們只需要對過濾器的類進(jìn)行擴(kuò)展,在構(gòu)造函數(shù)中傳入一些標(biāo)記進(jìn)去蛋济,然后進(jìn)行一些判斷出來棍鳖,這樣就能夠?qū)Y選過濾了。
權(quán)限驗(yàn)證過濾已經(jīng)完了碗旅,身份驗(yàn)證渡处,操作日志镜悉,和錯誤日志大致也是通過這些操作來完成了,AOP的編程思想骂蓖,將這些耦合性特別高的代碼實(shí)現(xiàn)了解耦积瞒,使用起來也非常的簡單,這才是真正優(yōu)雅的語法登下。
END