【全棧之路】web api權(quán)限攔截

最近接手了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的工程


image

2、選擇Empty 勾上web api


image

3征字、一個建好的空的web api項(xiàng)目


image

4都弹、新建一個控制器


image

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請求


image

我們先運(yùn)行項(xiàng)目(報錯不用管椎组,沒有設(shè)置默認(rèn)的路徑)


image
image

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


image
image

這個時候直接提交庐杨,會被重定向到error的Action,放回的結(jié)果為error Action的放回結(jié)果
image

這是返回上個頁面夹供,在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)限做這個事情。


image

這個時候再提交鸟辅,可以看到就能狗進(jìn)入test/test這個頁面了氛什。
image
再回過來看代碼,我們只需要在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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茫孔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子被芳,更是在濱河造成了極大的恐慌缰贝,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畔濒,死亡現(xiàn)場離奇詭異剩晴,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)侵状,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進(jìn)店門赞弥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人趣兄,你說我怎么就攤上這事绽左。” “怎么了艇潭?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵拼窥,是天一觀的道長。 經(jīng)常有香客問我蹋凝,道長鲁纠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任鳍寂,我火速辦了婚禮改含,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘迄汛。我一直安慰自己候味,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布隔心。 她就那樣靜靜地躺著白群,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硬霍。 梳的紋絲不亂的頭發(fā)上帜慢,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼粱玲。 笑死躬柬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抽减。 我是一名探鬼主播允青,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卵沉!你這毒婦竟也來了颠锉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤史汗,失蹤者是張志新(化名)和其女友劉穎琼掠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體停撞,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓷蛙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了戈毒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艰猬。...
    茶點(diǎn)故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖埋市,靈堂內(nèi)的尸體忽然破棺而出冠桃,到底是詐尸還是另有隱情,我是刑警寧澤恐疲,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站套么,受9級特大地震影響培己,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胚泌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一省咨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玷室,春花似錦零蓉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至津肛,卻和暖如春章喉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工秸脱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留落包,地道東北人。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓摊唇,卻偏偏與公主長得像咐蝇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子巷查,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容