Asp.net mvc 知多少(八)

本系列主要翻譯自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想看英文原版的可訪問http://www.dotnettricks.com/free-ebooks自行下載。該書主要分為兩部分,ASP.NET MVC 5、ASP.NET WEB API2。本書最大的特點是以面試問答的形式進行展開。通讀此書,會幫助你對ASP.NET MVC有更深層次的理解。
由于個人技術水平和英文水平也是有限的,因此錯誤在所難免,希望大家多多留言指正。
系列導航
Asp.net mvc 知多少(一)
Asp.net mvc 知多少(二)
Asp.net mvc 知多少(三)
Asp.net mvc 知多少(四)
Asp.net mvc 知多少(五)
Asp.net mvc 知多少(六)
Asp.net mvc 知多少(七)
Asp.net mvc 知多少(八)
Asp.net mvc 知多少(九)
Asp.net mvc 知多少(十)

本節主要講解過濾器

Q78. 介紹下ASP.NET MVC中的 Filters(過濾器) 和 Attributes(特性)?
Ans. ASP.NET MVC 提供了一種簡單的方式在action執行之前或之后注入一段代碼或邏輯,它就是ASP.NET MVC attributes,通過在Controller或者Action上使用Attributes來修飾即可。可以自定義過濾器或特性通過實現ASP.NET
MVC filter 接口或繼承并重載ASP.NET MVC filter attribute類。
通常,過濾器被用來執行以下常見的功能點:

  1. Custom Authentication(自定義認證)
  2. Custom Authorization (User based or Role based)(自定義授權-基于用戶或角色)
  3. Error handling or logging(異常處理或記錄日志)
  4. User Activity Logging(用戶活動日志)
  5. Data Caching(數據緩存)
  6. Data Compression(數據壓縮)

Q79. 介紹下ASP.NET MVC中幾種不同的Filters(過濾器) ?
Ans. 主要有以下五種類型Filters:
Authentication Filters(認證過濾器) - 該過濾器是從ASP.NET MVC5中引入的。IAuthenticationFilter接口是用來創建自定義認證過濾器。IAuthenticationFilter定義如下:

public interface IAuthenticationFilter
{
 void OnAuthentication(AuthenticationContext filterContext);
 void OnAuthenticationChallenge(AuthenticationChallengeContext
filterContext);
}

通過實現IAuthenticationFilter接口,即可實現自定義的認證過濾特性。

public class CustomAuthenticationFilterAttribute : FilterAttribute,
IAuthenticationFilter
{
 public void OnAuthentication(AuthenticationContext filterContext)
 {
 filterContext.HttpContext.Response.Write("Authentication
Filter<br/>");
 }
 //Runs after the OnAuthentication method
 public void OnAuthenticationChallenge(AuthenticationChallengeContext
filterContext)
 {
 //TODO: Additional tasks on the request
 }
}

Authorization Filters(授權過濾器) - ASP.NET MVC的授權過濾器實現了IAuthorizationFilter接口。

public interface IAuthorizationFilter
{
 void OnAuthorization(AuthorizationContext filterContext);
}

AuthorizeAttribute提供了以下可重載的方法:

public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
 protected virtual bool AuthorizeCore(HttpContextBase httpContext);
 protected virtual void HandleUnauthorizedRequest(AuthorizationContext
filterContext);
public virtual void OnAuthorization(AuthorizationContext filterContext);
 protected virtual HttpValidationStatus
OnCacheAuthorization(HttpContextBase httpContext);
}

所以,我們可以通過實現IAuthorizationFilter接口或者繼承AuthorizeAttribute類然后重載虛方法來創建自定義的授權過濾器。

Action Filters(操作過濾器) - Action filters 在action執行之前和之后執行。IActionFilter接口提供了OnActionExecutingOnActionExecuted 方法分別對應action之前和action之后執行。

public interface IActionFilter
{
 void OnActionExecuting(ActionExecutingContext filterContext);
 void OnActionExecuted(ActionExecutedContext filterContext);
}

** Result Filters(結果過濾器)** - Result filters在為action生成結果之前和和之后執行。返回的結果可以是 ViewResult、PartialViewResult、RedirectToRouteResult、RedirectResult、ContentResult、JsonResult、FileResult 和 EmptyResult ,它們均繼承自 ActionResult 類。Result filters 在Action Filters之后調用。
IResultFilter接口提供了OnResultExecutingOnResultExecuted 方法分別對應生成結果之前和之后執行。

public interface IResultFilter
{
 void OnResultExecuted(ResultExecutedContext filterContext);
 void OnResultExecuting(ResultExecutingContext filterContext);
}

** Exception Filters (異常過濾器)** - Exception filters在action或者過濾器執行期間出現異常時執行。IExceptionFilter接口提供了OnException方法來處理異常。

public interface IExceptionFilter
{
 void OnException(ExceptionContext filterContext);
}

HandleErrorAttribute類實現了IExceptionFilter接口。
HandleError接收到異常,它會直接返回ASP.NET MVC Views/Shared 文件夾下的Error視圖。


Q80. ASP.NET MVC的 Exception filters(異常過濾)何時執行?
Ans. Exception filters 在ASP.NET MVC pipeline(管道)執行期間有一個未處理的異常拋出時被執行。


Q81. ASP.NET MVC中filters(過濾器)的執行順序是?
Ans. 所有的 ASP.NET MVC filter都是按照一定的順序執行。 執行順序為:

  1. Authentication filters(認證過濾器)
  2. Authorization filters(授權過濾器)
  3. Action filters(操作過濾器)
  4. Result filters(結果過濾器)

Q82. ASP.NET MVC中如何配置過濾器?
Ans. 我們可以配置自定義的過濾器為以下三個級別:
Global level(全局級別)
將過濾器注冊到Global.asax.cs文件的Application_Start方法中:

protected void Application_Start()
{ FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}

Controller level(控制器級別)
通過將過濾器標記在controller上即可。

[Authorize(Roles = "Admin")]
public class AdminController : Controller
{
 //TODO:
}

Action level (操作級別)
通過將過濾器標記在action上即可。

public class UserController : Controller
{
 [Authorize(Users = "User1,User2")]
 public ActionResult LinkLogin(string provider)
 {
 // TODO:
 return View();
 }
}

Q83. ASP.NET MVC中認證和授權是如何工作的?
Ans. 像 ASP.NET一樣,MVC 也支持 Windows 和Forms 認證。可以通過在Web.config中配置或自己編碼。


Q84. ASP.NET MVC中 Forms Authentication 和 Authorization(表單認證和授權)是如何工作的?
Ans. 和 ASP.NET一樣, MVC Forms authentication在IIS認證完成之后發生??梢栽?ASP.NET MVC應用程序中的Web.config文件的forms節點進行配置。
默認的表單認證配置如下:

<system.web>
<authentication mode="Forms">
<forms loginUrl="Login.aspx"
protection="All"
timeout="30"
name=".ASPXAUTH"
path="/"
requireSSL="false"
slidingExpiration="true"
defaultUrl="default.aspx"
cookieless="UseDeviceProfile"
enableCrossAppRedirects="false" />
</authentication>
</system.web>
表單認證控制流程

SetAuthCookie()RedirectFromLoginPage()被調用時FormsAuthentication類自動創建認證Cookie。 Authentication cookie(認證Cookie)中包含一個已經加密和簽名的FormsAuthenticationTicket對象的字符串。
可以指定cookie的名稱、 版本、目錄路徑、生效日期、過期日期、是否永久屬性來創建FormsAuthenticationTicket對象 。

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "userName",
DateTime.Now,
DateTime.Now.AddMinutes(30), // value of time out property
false, // Value of IsPersistent property
String.Empty, FormsAuthentication.FormsCookiePath);

然后就可以使用FormsAuthentication類的Encrypt方法來加密ticket。
string encryptedTicket = FormsAuthentication.Encrypt(ticket);


Q85. ASP.NET MVC中如何實現自定義Forms Authentication and Authorization(表單認證和授權)?
Ans. 當標準的認證不能滿足你的需求,你就需要去修改認證機制去創建自定義的認證方案。一個用戶上下文有一個Principal,這個Principal代表用戶的身份(Identity)和角色(Role)。用戶通過ta的身份進行認證,通過給用戶分配角色來進行授權。

用戶上下文

ASP.NET 提供了IPrincipalIIdentity接口來表示用戶的身份和角色。這兩個接口
綁定到HttpContext對象和當前線程??梢酝ㄟ^實習這兩個接口來創建自定義的方案。

public class CustomPrincipal : IPrincipal
{
 public IIdentity Identity { get; private set; }
 public bool IsInRole(string role)
 {
 if (roles.Any(r => role.Contains(r)))
 {
 return true;
 }
 else
{
 return false;
 }
 }
 public CustomPrincipal(string Username)
 {
 this.Identity = new GenericIdentity(Username);
 }
 public int UserId { get; set; }
 public string FirstName { get; set; }
 public string LastName { get; set; }
 public string[] roles { get; set; }
}

現在你就可以把CustomPrincipal對象放入thread(線程)的 CurrentPrincipal屬性和HttpContext的User屬性來完成自定義的認證和授權流程。
如果IsAuthenticated返回true則表示用戶認證成功。我們可以用以下兩種方式來完成對用戶的驗證。

  1. Thread.CurrentPrincipal.Identity.IsAuthenticated
  2. HttpContext.Current.User.Identity.IsAuthenticated

ASP.NET MVC 提供了Authorization授權過濾器來對用戶授權。該過濾器可適用于action級別、控制器級別和全局級別。該過濾器基于AuthorizeAttribute特性類,可以通過繼承該特性并重載OnAuthorization()方法來對授權過濾器進行自定義。

public class CustomAuthorizeAttribute: AuthorizeAttribute {
    protected virtual CustomPrincipal CurrentUser {
        get {
            return HttpContext.Current.User as CustomPrincipal;
        }
    }
    public override void OnAuthorization(AuthorizationContext filterContext) {
        if (filterContext.HttpContext.Request.IsAuthenticated) {

            if (!String.IsNullOrEmpty(Roles)) {
                if (!CurrentUser.IsInRole(Roles)) {
                    filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new {
                        controller = "Error",
                        action = "AccessDenied"
                    }));
                }
            }
            if (!String.IsNullOrEmpty(Users)) {
                if (!Users.Contains(CurrentUser.UserId.ToString())) {
                    filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new {
                        controller = "Error",
                        action = "AccessDenied"
                    }));
                    // base.OnAuthorization(filterContext); //returns to login url
                }
            }
        }
    }
}

現在你就可以像下面這樣應用自定義的授權過濾器在控制器級別或者action級別。

[CustomAuthorize(Roles= "Admin")]
public class AdminController : BaseController
{
 public ActionResult Index()
 {
 return View();
 }
}

Q86. ASP.NET MVC如何允許輸入html tags?
Ans. ASP.NET MVC默認不允許用戶去提交html去避免Cross Site Scripting(CSS)攻擊 。
ValidateInput特性可以在action級別或controller級別啟用或禁用輸入校驗。

[ValidateInput(false)]
public class HomeController : Controller
{
 public ActionResult AddArticle()
 {
 return View();
 }
}

ValidateInput特性對所有屬性都允許html tag輸入,但這是不安全的。 如果你只是想針對部分屬性允許html輸入,可以通過為屬性添加AllowHtml 特性。

public class BlogModel
{
 [Required]
 [Display(Name = "Title")]
 public string Title { get; set; }
 [AllowHtml]
 [Required]
 [Display(Name = "Description")]
 public string Description { get; set; }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容