日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

认识ASP.NET MVC的5种AuthorizationFilter

發(fā)布時(shí)間:2024/4/15 asp.net 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 认识ASP.NET MVC的5种AuthorizationFilter 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在總體介紹了篩選器及其提供機(jī)制(《深入探討ASP.NET MVC的篩選器》)之后,我們按照?qǐng)?zhí)行的先后順序?qū)λ姆N不同的篩選器進(jìn)行單獨(dú)介紹,首先來介紹最先執(zhí)行的AuthorizationFilter。從命名來看,AuthorizationFilter用于完成授權(quán)相關(guān)的工作,所以它應(yīng)該在Action方法被調(diào)用之前執(zhí)行才能起到授權(quán)的作用。不僅限于授權(quán),如果我們希望目標(biāo)Action方法被調(diào)用之前中斷執(zhí)行的流程“做點(diǎn)什么”,都可以以AuthorizationFilter的形式來實(shí)現(xiàn)。[本文已經(jīng)同步到《How ASP.NET MVC Works?》中]

目錄?
一、IAuthorizationFilter?
二、AuthorizeAttribute?
三、RequireHttpsAttribute?
四、ValidateInputAttribute?
五、ValidateAntiForgeryTokenAttribute?
六、ChildActionOnlyAttribute

一、IAuthorizationFilter

所有的AuthorizationFilter實(shí)現(xiàn)了接口IAuthorizationFilter。如下面的代碼片斷所示,IAuthorizationFilter定義了一個(gè)OnAuthorization方法用于實(shí)現(xiàn)授權(quán)的操作。作為該方法的參數(shù)filterContext是一個(gè)表示授權(quán)上下文的AuthorizationContext對(duì)象, 而AuthorizationContext直接繼承自ControllerContext。

1: public interface IAuthorizationFilter 2: { 3: void OnAuthorization(AuthorizationContext filterContext); 4: } 5:? 6: public class AuthorizationContext : ControllerContext 7: { 8: public AuthorizationContext(); 9: public AuthorizationContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor); 10: 11: public virtual ActionDescriptor ActionDescriptor { get; set; } 12: public ActionResult Result { get; set; } 13: }

AuthorizationContext的ActionDescriptor屬性表示描述當(dāng)前執(zhí)行Action的ActionDescriptor對(duì)象,而Result屬性返回一個(gè)用于在授權(quán)階段呈現(xiàn)的ActionResult。AuthorizationFilter的執(zhí)行是ActionInvoker進(jìn)行Action執(zhí)行的第一項(xiàng)工作,因?yàn)楹罄m(xù)的工作(Model綁定、Model驗(yàn)證、Action方法執(zhí)行等)只有在成功授權(quán)的基礎(chǔ)上才會(huì)有意義。

ActionInvoker在通過執(zhí)行AuthorizationFilter之前,會(huì)先根據(jù)當(dāng)前的Controller上下文和解析出來的用于描述當(dāng)前Action的ActionDescriptor,并以此創(chuàng)建一個(gè)表示授權(quán)上下文的AuthorizationContext對(duì)象。然后將此AuthorizationContext對(duì)象作為參數(shù),按照Filter對(duì)象Order和Scope屬性決定的順序執(zhí)行所有AuthorizationFilter的OnAuthorization。

在所有的AuthorizationFilter都執(zhí)行完畢之后,如果指定的AuthorizationContext對(duì)象的Result屬性表示得ActionResult不為Null,整個(gè)Action的執(zhí)行將會(huì)終止,而ActionInvoker將會(huì)直接執(zhí)行該ActionResult。一般來說,某個(gè)AuthorizationFilter在對(duì)當(dāng)前請(qǐng)求實(shí)施授權(quán)的時(shí)候,如果授權(quán)失敗它可以通過設(shè)置傳入的AuthorizationContext對(duì)象的Result屬性響應(yīng)一個(gè)“401,Unauthrized”回復(fù),或者呈現(xiàn)一個(gè)錯(cuò)誤頁面。

二、AuthorizeAttribute

如果我們要求某個(gè)Action只能被認(rèn)證的用戶訪問,可以在Controller類型或者Action方法上應(yīng)用具有如下定義的AuthorizeAttribute特性。AuthorizeAttribute還可以具體限制目標(biāo)Action可被訪問的用戶或者角色,它的Users和Roles屬性用于指定被授權(quán)的用戶名和角色列表,中間用采用逗號(hào)作為分隔符。如果沒有顯式地對(duì)Users和Roles屬性進(jìn)行設(shè)置,AuthorizeAttribute在進(jìn)行授權(quán)操作的時(shí)候只要求訪問者是被認(rèn)證的用戶。

1: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=true)] 2: public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter 3: { 4: //其他成員 5: public virtual void OnAuthorization(AuthorizationContext filterContext); 6: protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext); 7: 8: public string Roles { get; set; } 9: public override object TypeId { get; } 10: public string Users { get; set; } 11: }

如果授權(quán)失敗(當(dāng)前訪問者是未被授權(quán)用戶,或者當(dāng)前用戶的用戶名或者角色沒有在指定的授權(quán)用戶或者角色列表中),AuthorizeAttribute會(huì)創(chuàng)建一個(gè)HttpUnauthorizedResult對(duì)象,并賦值給AuthorizationContext的Result屬性,意味著會(huì)響應(yīng)一個(gè)狀態(tài)為“401,Unauthorized”的回復(fù)。如果采用Forms認(rèn)證,配置的登錄頁面會(huì)自動(dòng)被顯示。

很多會(huì)將AuthorizeAttribute對(duì)方法的授權(quán)與PrincipalPermissionAttribute等同起來,實(shí)際上不但它們實(shí)現(xiàn)授權(quán)的機(jī)制不一樣(后者是通過代碼訪問安全檢驗(yàn)實(shí)現(xiàn)對(duì)方法調(diào)用的授權(quán)),它們的授權(quán)策略也一樣。以下面定義的兩個(gè)方法為例,應(yīng)用了PrincipalPermissionAttribute的FooOrAdmin意味著可以被帳號(hào)為Foo或者具有Admin角色的用戶訪問,而應(yīng)用了AuthorizeAttribute特性的方法FooAndAdmin方法則只能被用戶Foo訪問,而且該用戶必須具有Admin角色。也就是說PrincipalPermissionAttribute特性對(duì)User和Role的授權(quán)邏輯是“邏輯或”,而AuthorizeAttribute 采用的則是“邏輯與”。

1: [PrincipalPermission( SecurityAction.Demand,Name="Foo", Role="Admin")] 2: public void FooOrAdmin() 3: { } 4:? 5: [Authorize(Users="Foo", Roles="Admin")] 6: public void FooAndAdmin() 7: { }

除此之外,我們可以將多個(gè)PrincipalPermissionAttribute和AuthorizeAttribute應(yīng)用到同一個(gè)類型或者方法上。對(duì)于前者,如果當(dāng)前用于通過了任意一個(gè)PrincipalPermissionAttribute特性的授權(quán)就有權(quán)調(diào)用目標(biāo)方法;對(duì)于后者來說,意味著需要通過所有AuthorizeAttribute特性的授權(quán)在具有了調(diào)用目標(biāo)方法的權(quán)限。以如下兩個(gè)方法為例,用戶Foo或者Bar可以有權(quán)限調(diào)用FooOrBar方法,但是沒有任何一個(gè)用戶有權(quán)調(diào)用CannotCall方法(因?yàn)橐粋€(gè)用戶只一個(gè)用戶名)。

1: [PrincipalPermission( SecurityAction.Demand, Name="Foo") 2: [PrincipalPermission( SecurityAction.Demand, Name="Bar")] 3: public void FooOrBar() 4: { } 5:? 6: [Authorize(Users="Foo")] 7: [Authorize(Users="Bar")] 8: public void CannotCall() 9: {}

?

三、RequireHttpsAttribute

從名稱也可以看出來來,RequireHttpsAttribute這個(gè)AuthorizationFilter要求用用戶總是以HTTP請(qǐng)求的方式訪問目標(biāo)方法。如果當(dāng)前并不是一個(gè)HTTPS請(qǐng)求(通過當(dāng)前HttpRequest的IsSecureConnection屬性判斷),在HTTP方法為GET的情下,會(huì)創(chuàng)建一個(gè)RedirectResult對(duì)象并用其對(duì)AuthorizationContext的Result屬性進(jìn)行設(shè)置,當(dāng)前請(qǐng)求的URL地址的Scheme替換成HTTPS就成了該RedirectResult的地址。也就是說,如果當(dāng)前請(qǐng)求地址為http://www.artech.com/home/index,會(huì)自動(dòng)重定向到https://www.artech.com/home/index。

1: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)] 2: public class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter 3: { 4: protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext); 5: public virtual void OnAuthorization(AuthorizationContext filterContext); 6: }

如果當(dāng)前請(qǐng)求的HTTP方法并不是GET,RequireHttpsAttribute會(huì)直接拋出一個(gè)InvalidOperationException異常。如上面的代碼片斷所示,針對(duì)非HTTPS請(qǐng)求的處理通過調(diào)用受保護(hù)的方法HandleNonHttpsRequest來完成,如果我們需要不同的處理,可以繼承RequireHttpsAttribute并重寫該方法。

四、ValidateInputAttribute

為了避免用戶在請(qǐng)求中包含一些不合法的內(nèi)容對(duì)網(wǎng)站進(jìn)行惡意攻擊(比如XSS攻擊),我們一般需要對(duì)請(qǐng)求的輸入進(jìn)行驗(yàn)證。如下面的代碼片斷所示,表示HTTP請(qǐng)求的基類HttpRequestBase具有一個(gè)ValidateInput方法用于驗(yàn)證請(qǐng)求的輸入。實(shí)際上這個(gè)方法僅僅是在請(qǐng)求上作一下標(biāo)記而已,在讀取相應(yīng)的請(qǐng)求輸入時(shí)才根據(jù)這些表示決定是否需要進(jìn)行相應(yīng)的驗(yàn)證。不過為了便于表達(dá),我們就將針對(duì)該ValidateInput方法的調(diào)用說成是針對(duì)請(qǐng)求輸入的驗(yàn)證。

1: public abstract class HttpRequestBase 2: { 3: //其他成員 4: public virtual void ValidateInput(); 5: }

所有Controller的基類ControllerBase具有如下一個(gè)布爾類型的屬性ValidateRequest表示是否需要對(duì)請(qǐng)求輸入進(jìn)行驗(yàn)證,在默認(rèn)情況下該屬性的默認(rèn)值為True,意味著針對(duì)請(qǐng)求輸入的驗(yàn)證默認(rèn)情況下是開啟的。 當(dāng)ActionInvoker在完成了對(duì)所有AuthorizationFilter的執(zhí)行之后,會(huì)根據(jù)該屬性決定是否會(huì)通過調(diào)用表示當(dāng)前請(qǐng)求的HttpRequest對(duì)象的ValidateInput方法進(jìn)行請(qǐng)求輸入的驗(yàn)證。

1: public abstract class ControllerBase : IController 2: { 3: //其他成員 4: public bool ValidateRequest { get; set; } 5: }

也正是由于ActionInvoker針對(duì)請(qǐng)求輸入驗(yàn)證是在完成了所有AuthorizationFilter的執(zhí)行之后進(jìn)行的,所以我們可以通過自定義AuthorizationFilter的方式來設(shè)置當(dāng)前Controller的ValidateRequest屬性進(jìn)而開啟或者關(guān)閉針對(duì)請(qǐng)求輸入的驗(yàn)證。ValidateInputAttribute就是這么做的,我們可以從如下表示ValidateInputAttribute的定義看出來(構(gòu)造函數(shù)的參數(shù)enableValidation表示是否啟動(dòng)針對(duì)請(qǐng)求的輸入驗(yàn)證)。

1: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)] 2: public class ValidateInputAttribute : FilterAttribute, IAuthorizationFilter 3: { 4: public ValidateInputAttribute(bool enableValidation) 5: { 6: this.EnableValidation = enableValidation; 7: } 8:? 9: public virtual void OnAuthorization(AuthorizationContext filterContext) 10: { 11: if (filterContext == null) 12: { 13: throw new ArgumentNullException("filterContext"); 14: } 15: filterContext.Controller.ValidateRequest = this.EnableValidation; 16: } 17:? 18: public bool EnableValidation { get; private set; } 19: }

為了讓讀者對(duì)ValidateInputAttribute這個(gè)AuthorizationFilter針對(duì)開啟和關(guān)閉輸入驗(yàn)證的作用有一個(gè)深刻映像,我們來進(jìn)行一個(gè)簡(jiǎn)單的實(shí)例演示。在通過Visual Studio的ASP.NET MVC項(xiàng)目模板創(chuàng)建的空Web應(yīng)用中我們 定義了如下一個(gè)HomeController,包含在該Controller中的兩個(gè)Action方法(Action1和Action2)具有一個(gè)字符串類型的參數(shù)foo,其中Action1上應(yīng)用了ValidateInputAttribute特性并將參數(shù)設(shè)置為False。

1: public class HomeController : Controller 2: { 3: [ValidateInput(false)] 4: public void Action1(string foo, string bar) 5: { 6: Response.Write(string.Format("{0}: {1}<br/>", "foo", Server.HtmlEncode(foo))); 7: Response.Write(string.Format("{0}: {1}<br/>", "bar", Server.HtmlEncode(bar))); 8: } 9:? 10: public void Action2(string foo, string bar) 11: { 12: Response.Write(string.Format("{0}: {1}<br/>", "foo", Server.HtmlEncode(foo))); 13: Response.Write(string.Format("{0}: {1}<br/>", "bar", Server.HtmlEncode(bar))); 14: } 15: }

我們直接運(yùn)行該程序并在瀏覽器中通過輸入相應(yīng)的地址來訪問這兩個(gè)Action,并以查詢字符串的形式指定它們的兩個(gè)參數(shù)。為了檢驗(yàn)ASP.NET MVC對(duì)請(qǐng)求輸入的驗(yàn)證,我們將表示參數(shù)foo的查詢字符串的值設(shè)置為為“<script></script>”。如下圖所示,Action1能夠正常地被調(diào)用,而Action2在調(diào)用過程中拋出異常 ,并提示請(qǐng)求中包含危險(xiǎn)的查詢字符串。

在《ASP.NET MVC Model元數(shù)據(jù)及其定制:一個(gè)重要的接口IMetadataAware》中我們談到可以通過AllowHtmlAttribute特性來定義表示Model元數(shù)據(jù)的ModelMetadata的RequestValidationEnabled屬性的設(shè)置從而忽略對(duì)相應(yīng)屬性數(shù)據(jù)的驗(yàn)證,使之可以包含具有HTML標(biāo)簽的數(shù)據(jù)。這與ValidateInputAttribute的作用類似,不同的是AllowHtmlAttribute僅僅針對(duì)Model對(duì)象的默認(rèn)屬性,而ValidateInputAttribute則是針對(duì)整個(gè)請(qǐng)求。

五、ValidateAntiForgeryTokenAttribute

具有如下定義的System.Web.Mvc.ValidateAntiForgeryTokenAttribute用于解決一種叫做“跨站請(qǐng)求偽造(CSRF:Cross-Site Request Forgery)”。這是一種不同于XSS(Cross Site Script)的跨站網(wǎng)絡(luò)攻擊,如果說XSS是利用了用戶對(duì)網(wǎng)站的信任,而CSRF就是利用了站點(diǎn)對(duì)認(rèn)證用戶的信任。

1: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=false, Inherited=true)] 2: public sealed class ValidateAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter 3: { 4: public ValidateAntiForgeryTokenAttribute(); 5: public void OnAuthorization(AuthorizationContext filterContext); 6: public string Salt { get; set; } 7: }

我們通過一個(gè)簡(jiǎn)單的例子來對(duì)CSRF的原理進(jìn)行說明。假設(shè)我們通過ASP.NET MVC構(gòu)建了一個(gè)博客應(yīng)用,作為博主的用戶可以發(fā)表博文,而一般用于可以對(duì)博文發(fā)表評(píng)論。除此之外,注冊(cè)用于可以修改自己的Email地址,相關(guān)的操作定義在如下所示的BlogController的Action方法UpdateAddress中。

1: public class BlogController: Controller 2: { 3: [Authorize] 4: [HttpPost] 5: public void UpdateEmailAddress(string emailAddress) 6: { 7: //Email地址修改操作 8: } 9: //其他成員 10: }

對(duì)于上面定義的UpdateEmailAddress方法,由于應(yīng)用了AuthorizeAttribute特性,意味著只有認(rèn)證的用戶才能調(diào)用它來修改自己提供的Email地址。此外,HttpPostAttribute特性應(yīng)用在該Action方法上,使我們只能以POST請(qǐng)求的方式調(diào)用它,這無形之中也增強(qiáng)了安全系數(shù)。但是這個(gè)方法提供的Email修改功能真的安全嗎?它真的確保修改后的Email地址真的是登錄用戶提供的Email地址嗎?

我們假設(shè)BlogController所在的Web應(yīng)用部署的域名為Foo,那么Action方法UpdateEmailAddress對(duì)應(yīng)的地址可以表示為http://foo/blog/updateemailaddress?,F(xiàn)在一個(gè)惡意攻擊者創(chuàng)建如下一個(gè)簡(jiǎn)單的HTML頁面,該頁面具有一個(gè)指向上面這個(gè)地址的表單,并且該表單中具有一個(gè)名為emailAddress <input>元素提供屬于供給者自身的Email地址。由于注冊(cè)了window的onload事件,該表單會(huì)在頁面加載完成之后自動(dòng)提交。

1: <html> 2: <head> 3: <script type="text/javascript"> 1:? 2: window.onload = function () { 3: document.getElementById("updateEmail").submit(); 4: } 5: </script> 4: </head> 5: <body> 6: <form id="updateEmail" action="http://foo/blog/updateemailaddress" 7: method="post"> 8: <input type="hidden" name="emailAddress" value="malicious@gmail.com" /> 9: </form> 10: </body> 11: </html>

假設(shè)攻擊者部署該頁面的地址為http://bar/maliciouspage.html。然后它通過某篇博文中添加一個(gè)包含如下鏈接的評(píng)論。作為登錄用戶的你點(diǎn)擊該連接后將會(huì)間接地調(diào)用定義在BlogController的UpdateEmailAddress方法。由于登錄用戶的安全令牌一般以Cookie形式存在,而該Cookie會(huì)存在于發(fā)送給針對(duì)Action方法UpdateEmailAddress的調(diào)用請(qǐng)求中,服務(wù)器會(huì)認(rèn)為該請(qǐng)求來自被認(rèn)證用戶,所以最終造成了你的Email地址被惡意修改而不自知。如果攻擊者具有你的用戶名,它可以通過重置密碼,是新的密碼發(fā)送到屬于他自己的電子郵箱中。

1: <img src="http://bar/maliciouspage.html"/>

這個(gè)例子充分說明了CSRF是一種比較隱蔽并且具有很大危害型的網(wǎng)絡(luò)攻擊,促成攻擊的原因在于服務(wù)器在針對(duì)某個(gè)請(qǐng)求執(zhí)行某個(gè)操作的時(shí)候并沒有驗(yàn)證請(qǐng)求的真正來源。對(duì)于ASP.NET MVC來說,如果我們?cè)趫?zhí)行某個(gè)Action方法之前能夠確認(rèn)當(dāng)前的請(qǐng)求來源的有效性,就能從根本上解決CSRF攻擊,而ValidateAntiForgeryTokenAttribute結(jié)合HtmlHelper的AntiForgeryToken方法有效地解決了這個(gè)問題。

1: public class HtmlHelper 2: { 3: //其他成員 4: public MvcHtmlString AntiForgeryToken(); 5: public MvcHtmlString AntiForgeryToken(string salt); 6: public MvcHtmlString AntiForgeryToken(string salt, string domain, string path); 7: }

如上面的代碼片斷所示,HtmlHelper具有三個(gè)AntiForgeryToken方法(這里的方式是HtmlHelper的實(shí)例方法,不是擴(kuò)展方法)。當(dāng)我們?cè)谝粋€(gè)View中調(diào)用這些方法是,它們會(huì)為我們生成一個(gè)所謂“防偽令牌(Anti-Forgery Token)”的字符串,并以此生成一個(gè)類型為Hidden的<input>元素。除此之外,該方法的調(diào)用還會(huì)根據(jù)這個(gè)防偽令牌設(shè)置一個(gè)Cookie。接下來我們來詳細(xì)地來討論這個(gè)過程。

上述的這個(gè)防偽令牌通過內(nèi)部類型為AntiForgeryData的對(duì)象生成。如下面的代碼片斷所示,AntiForgeryData具有四個(gè)屬性,其核心是通過屬性Value表示的值。屬性UserName和CreationDate表示訪問令牌授權(quán)的用戶名和創(chuàng)建時(shí)間。字符串屬性Salt是為了增強(qiáng)防偽令牌的安全系數(shù),不同的Salt值對(duì)應(yīng)著不同的防偽令牌,不同的防偽令牌在不同的地方被使用以避免供給者對(duì)一個(gè)防偽令牌的破解而使整個(gè)應(yīng)用受到全面的攻擊。ValidateAntiForgeryTokenAttribute也具有一個(gè)同名的屬性。

1: internal sealed class AntiForgeryData 2: { 3: public string Value { get; set; } 4: public string Salt { get; set; } 5: public DateTime CreationDate { get; set; } 6: public string Username { get; set; } 7: }

當(dāng)AntiForgeryToken被調(diào)用的時(shí)候,會(huì)先根據(jù)當(dāng)前的請(qǐng)求的應(yīng)用路徑(對(duì)應(yīng)HttpRequest的ApplicationPath屬性)計(jì)算出表示防偽令牌Cookie的名稱,該名稱會(huì)在通過對(duì)應(yīng)用路徑進(jìn)行Base64編碼(編碼之前需要進(jìn)行一些特殊字符的替換工作)生成的字符串前添加“__RequestVerificationToken”前綴。

如果當(dāng)前請(qǐng)求具有一個(gè)同名的Cookie,則直接通過對(duì)Cookie的值進(jìn)行反序列化得到一個(gè)AntiForgeryData對(duì)象。需要注意的是,這里針對(duì)AntiForgeryData進(jìn)行序列化和反序列化并不是一個(gè)簡(jiǎn)單地實(shí)現(xiàn)運(yùn)行時(shí)對(duì)象到字符串之間的轉(zhuǎn)換,還包含采用MachineKey對(duì)AntiForgeryData的四個(gè)屬性進(jìn)行加密/解密的過程。如果這樣的Cookie不存在,HtmlHelper會(huì)隨機(jī)生成一個(gè)長(zhǎng)度為16的字節(jié)數(shù)組,并將對(duì)該字節(jié)數(shù)組進(jìn)行Base64編碼后生成的字符串作為值創(chuàng)建一個(gè)AntiForgeryData對(duì)象。系統(tǒng)當(dāng)前時(shí)間(UTC)作為該AntiForgeryData對(duì)象的創(chuàng)建時(shí)間,但是該AntiForgeryData對(duì)象的UserName和Salt屬性為空。

接下來HtmlHelper會(huì)根據(jù)之前計(jì)算出來的Cookie名稱創(chuàng)建一個(gè))HttpCookie對(duì)象,而新創(chuàng)建出來的AntiForgeryData對(duì)象被序列化后生成的字符串作為該HttpCookie的值。如果我們?cè)贏ntiForgeryToken方法調(diào)用中設(shè)置了表示域和路徑的domain和path參數(shù),它們將會(huì)作為該HttpCookie對(duì)象的Path和Domain屬性。最后HtmlHelper將HttpCookie對(duì)象設(shè)置給當(dāng)前的HTTP響應(yīng)。

AntiForgeryToken返回的是一個(gè)類型為hidden的<input>元素對(duì)應(yīng)的HTML,該Hidden元素的名稱為“__RequestVerificationToken”(即代碼訪問令牌Cookie名稱的前綴)。為了生成該Hidden元素的值,HtmlHelper會(huì)根據(jù)現(xiàn)有的AntiForgeryData對(duì)象(從當(dāng)前請(qǐng)求獲取的或者新創(chuàng)建的)創(chuàng)建一個(gè)新的AntiForgeryData對(duì)象,兩個(gè)對(duì)象具有相同的CreationDate和Value屬性,而當(dāng)前用戶名和指定的Salt參數(shù)將會(huì)設(shè)置給新AntiForgeryData對(duì)象的UserName和Salt屬性。

1: @using (Html.BeginForm()) 2: { 3: @Html.AntiForgeryToken("647B8734-EFCA-4F51-9D98-36502D13E4E7") 4: ... 5: }

在一個(gè)View中我們通過如上的代碼在一個(gè)表單中調(diào)用HtmlHelper的AntiForgeryToken方法并將一個(gè)GUID作為Salt,最終將會(huì)生成如下一個(gè)名為“__RequestVerificationToken”的Hidden元素。

1: <form action="..." method="post"> 2: <input name="__RequestVerificationToken" type="hidden" value="yvLaFQ81JVgguKECyF/oQ+pc2/6q0MuLEaF73PvY7pvxaE68lO5qgXZWhfqIk721CBS0SJZjvOjbc7o7GL3SQ3RxIW90no7FcxzR6ohHUYEKdxyfTBuAVjAuoil5miwoY8+6HNoSPbztyhMVvtCsQDtvQfyW1GNa7qvlQSqYxQW7b6nAR2W0OxNi4NgrFEqbMFrD+4CwwAg4PUWpvcQxYA==" /> 3: ... 4: </form>

對(duì)于該View的首次訪問(或者對(duì)應(yīng)的Cookie不存在),如下所示的名稱為“__RequestVerificationToken_L012Y0FwcDEx”防偽令牌Cookie將會(huì)設(shè)置,并且是HttpOnly的。

1: HTTP/1.1 200 OK 2: Cache-Control: private 3: ... 4: Set-Cookie: __RequestVerificationToken_L012Y0FwcDEx=EYPOofprbB0og8vI+Pzr1unY0Ye5BihYJgoIYBqzvZDZ+hcT5QUu+fj2hvFUVTTCFAZdjgCPzxwIGsoNdEyD8nSUbgapk8Xp3+ZD8cxguUrgl0lAdFd4ZGWEYzz0IN58l5saPJpuaChVR4QaMNbilNG4y7xiN2/UCrBF80LmPO4=; path=/; HttpOnly 5: ...

對(duì)于一個(gè)請(qǐng)求,如果確保請(qǐng)求提供的表單中具有一個(gè)名為“__RequestVerificationToken”的Hidden元素,并且該元素的值與對(duì)應(yīng)的防偽令牌的Cookie值相匹配,就能夠確保請(qǐng)求并不是由第三方惡意站點(diǎn)發(fā)送的,進(jìn)而防止CSRF攻擊。原因很簡(jiǎn)單:由于Cookie值是經(jīng)過加密的,供給者可以得到整個(gè)Cookie的內(nèi)容,但是不能解密獲得具體的值(AntiForgeryData的Value屬性),所以不可能在提供的表單中也包含一個(gè)具有匹配值的Hidden元素。針對(duì)防偽令牌的驗(yàn)證就實(shí)現(xiàn)在ValidateAntiForgeryTokenAttribute的OnAuthorization方法中。

我們來具體介紹一下實(shí)現(xiàn)在ValidateAntiForgeryTokenAttribute中針對(duì)防偽令牌的驗(yàn)證邏輯。首先它根據(jù)當(dāng)前請(qǐng)求的應(yīng)用路徑采用與生成防偽令牌Cookie相同的邏輯計(jì)算出Cookie名稱。如果對(duì)應(yīng)的Cookie不存在于當(dāng)前請(qǐng)求中,則直接拋出HttpAntiForgeryException異常;否則獲取Cookie值,并反序列化生成一個(gè)AntiForgeryData對(duì)象。

然后從提交的表單中提取一個(gè)名稱為“__RequestVerificationToken”的輸入元素,如果這樣的元素不存在,同樣拋出HttpAntiForgeryException異常;否則直接對(duì)具體的值進(jìn)行反序列化生成一個(gè)AntiForgeryData對(duì)象。最后ValidateAntiForgeryTokenAttribute對(duì)這兩個(gè)AntiForgeryData的Value屬性進(jìn)行比較,以及后者的UserName和Salt屬性與當(dāng)前用戶名和自身的Salt屬性值進(jìn)行比較,任何一個(gè)不匹配都會(huì)拋出HttpAntiForgeryException異常。

六、ChildActionOnlyAttribute

如果我們希望定義在Controol中的方法能以子Action的形式在某個(gè)View中被調(diào)用,這樣的調(diào)用一般用于生成組成整個(gè)View的某個(gè)部分的HTML,我們可以在方法上應(yīng)用ChildActionOnlyAttribute特性。從如下給出的定義可以看出,ChildActionOnlyAttribute實(shí)際上是一個(gè)AuthorizationFilter,它在重寫的OnAuthorization方法中對(duì)當(dāng)前請(qǐng)求進(jìn)行驗(yàn)證,對(duì)于非子Action調(diào)用下直接拋出InvalidOperationException異常。

1: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=false, Inherited=true)] 2: public sealed class ChildActionOnlyAttribute : FilterAttribute, IAuthorizationFilter 3: { 4: public void OnAuthorization(AuthorizationContext filterContext); 5: }

有的讀者可能會(huì)問,AuthorizationFilter如何區(qū)分當(dāng)前的請(qǐng)求是基于子Action的調(diào)用,而不是一般的Action調(diào)用呢?其實(shí)很簡(jiǎn)單,當(dāng)我們?cè)谡{(diào)用HtmlHelper的擴(kuò)展方法Action或者RenderAction的時(shí)候會(huì)將當(dāng)前的View上下文作為“父View上下文”保存到表示當(dāng)前路由信息的RouteData的DataTokens屬性中,對(duì)應(yīng)的Key為“ParentActionViewContext”。如下面的代碼片斷所示,ControllerContext中用于判斷是否為子Action請(qǐng)求的IsChildAction屬性正式通過該路由信息進(jìn)行判斷的。

1: public class ControllerContext 2: { 3: //其他成員 4: public virtual bool IsChildAction 5: { 6: get 7: { 8: RouteData routeData = this.RouteData; 9: if (routeData == null) 10: { 11: return false; 12: } 13: return routeData.DataTokens.ContainsKey("ParentActionViewContext"); 14: } 15: } 16: }

轉(zhuǎn)載于:https://www.cnblogs.com/sylone/p/6094695.html

總結(jié)

以上是生活随笔為你收集整理的认识ASP.NET MVC的5种AuthorizationFilter的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 韩国电影大尺度在线观看 | 欧亚免费视频 | 亚洲在线视频播放 | 亚洲天堂一区在线观看 | 免费观看a视频 | аⅴ资源新版在线天堂 | 啪啪天堂 | 久久嫩草精品久久久久 | 99视频精品免费 | 一区二区三区国产精品视频 | 成人在线免费播放视频 | 偷偷操不一样 | 综合久久国产 | 日本亚洲欧美在线 | 午夜精品一区二区三区在线播放 | 亚洲国产私拍精品国模在线观看 | 奇米色777| 久久神马影院 | 国产成人精品一区二区三区无码熬 | 河北彩花av在线播放 | 有码视频在线观看 | 337p色噜噜| 亚洲国产日韩一区二区 | 国产人妻一区二区三区四区五区六 | 日韩a√ | 亚洲高潮 | 亚洲一级片免费 | 人妻无码一区二区三区免费 | 黄色大片在线免费观看 | 清冷学长被爆c躁到高潮失禁 | 久久久av免费 | 污视频免费在线观看 | 99在线精品视频免费观看20 | 欧美香蕉网 | 亚洲黄视频 | 黄视频网站免费看 | 99国产精品白浆在线观看免费 | 不卡一二三 | 最新欧美大片 | 亚洲尤物视频 | 最新极品jizzhd欧美 | 欧美日韩成人一区二区在线观看 | 91视频国产精品 | 任你躁av一区二区三区 | 欧美日韩一二三区 | 三上悠亚 在线观看 | 亚洲区欧美 | 日韩欧美a级片 | 毛片99| 久久国色 | 久操视频在线免费观看 | 午夜片在线观看 | 村上里沙番号 | 国产在线观看第一页 | 在线观看国产一区二区三区 | 怡春院视频 | 2018av在线| 五月天激情开心网 | 在线播放av网址 | 动漫美女被吸乳奶动漫视频 | 中文字幕女同女同女同 | 中文字幕在线观看你懂的 | 337p粉嫩日本欧洲亚洲大胆 | 成人超碰在线 | 波多野结av衣东京热无码专区 | 国产永久免费观看 | www.在线播放| 四虎精品成人免费网站 | 久久久精品麻豆 | 91丨九色丨丰满 | 亚洲精华国产精华精华液网站 | 女教师高潮黄又色视频 | 天天射夜夜撸 | 国产综合日韩 | 国产精品久久久精品 | 色香天天| 男女日日 | 欧美天天影院 | 欧美激情视频一区二区三区不卡 | 麻豆精品在线 | 亚洲熟妇无码另类久久久 | a猛片| 国产区视频在线 | 欧美乱妇一区二区三区 | 尹人在线视频 | 黄视频在线 | 国产黄色网址在线观看 | 日产mv免费观看 | 免费在线h | 中文字幕av一区二区 | 亚洲欧美在线成人 | 97公开免费视频 | www.狠狠插 | 毛茸茸日本熟妇高潮 | 中文永久免费观看 | 91成人在线播放 | 成人免费视频视频 | 色眯眯影院 | 丰满少妇一区 |