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。本書最大的特點(diǎn)是以面試問答的形式進(jìn)行展開。通讀此書,會(huì)幫助你對(duì)ASP.NET MVC有更深層次的理解。
由于個(gè)人技術(shù)水平和英文水平也是有限的,因此錯(cuò)誤在所難免,希望大家多多留言指正。
系列導(dǎo)航
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 知多少(十)

本節(jié)主要講解過濾器

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

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

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

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

通過實(shí)現(xiàn)IAuthenticationFilter接口,即可實(shí)現(xiàn)自定義的認(rèn)證過濾特性。

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(授權(quán)過濾器) - ASP.NET MVC的授權(quán)過濾器實(shí)現(xiàn)了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);
}

所以,我們可以通過實(shí)現(xiàn)IAuthorizationFilter接口或者繼承AuthorizeAttribute類然后重載虛方法來創(chuàng)建自定義的授權(quán)過濾器。

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

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

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

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

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

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

HandleErrorAttribute類實(shí)現(xiàn)了IExceptionFilter接口。
當(dāng)HandleError接收到異常,它會(huì)直接返回ASP.NET MVC Views/Shared 文件夾下的Error視圖。


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


Q81. ASP.NET MVC中filters(過濾器)的執(zhí)行順序是?
Ans. 所有的 ASP.NET MVC filter都是按照一定的順序執(zhí)行。 執(zhí)行順序?yàn)椋?/p>

  1. Authentication filters(認(rèn)證過濾器)
  2. Authorization filters(授權(quán)過濾器)
  3. Action filters(操作過濾器)
  4. Result filters(結(jié)果過濾器)

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

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

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

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

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

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

Q83. ASP.NET MVC中認(rèn)證和授權(quán)是如何工作的?
Ans. 像 ASP.NET一樣,MVC 也支持 Windows 和Forms 認(rèn)證??梢酝ㄟ^在Web.config中配置或自己編碼。


Q84. ASP.NET MVC中 Forms Authentication 和 Authorization(表單認(rèn)證和授權(quán))是如何工作的?
Ans. 和 ASP.NET一樣, MVC Forms authentication在IIS認(rèn)證完成之后發(fā)生??梢栽?ASP.NET MVC應(yīng)用程序中的Web.config文件的forms節(jié)點(diǎn)進(jìn)行配置。
默認(rèn)的表單認(rèn)證配置如下:

<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>
表單認(rèn)證控制流程

當(dāng)SetAuthCookie()RedirectFromLoginPage()被調(diào)用時(shí)FormsAuthentication類自動(dòng)創(chuàng)建認(rèn)證Cookie。 Authentication cookie(認(rèn)證Cookie)中包含一個(gè)已經(jīng)加密和簽名的FormsAuthenticationTicket對(duì)象的字符串。
可以指定cookie的名稱、 版本、目錄路徑、生效日期、過期日期、是否永久屬性來創(chuàng)建FormsAuthenticationTicket對(duì)象 。

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中如何實(shí)現(xiàn)自定義Forms Authentication and Authorization(表單認(rèn)證和授權(quán))?
Ans. 當(dāng)標(biāo)準(zhǔn)的認(rèn)證不能滿足你的需求,你就需要去修改認(rèn)證機(jī)制去創(chuàng)建自定義的認(rèn)證方案。一個(gè)用戶上下文有一個(gè)Principal,這個(gè)Principal代表用戶的身份(Identity)和角色(Role)。用戶通過ta的身份進(jìn)行認(rèn)證,通過給用戶分配角色來進(jìn)行授權(quán)。

用戶上下文

ASP.NET 提供了IPrincipalIIdentity接口來表示用戶的身份和角色。這兩個(gè)接口
綁定到HttpContext對(duì)象和當(dāng)前線程。可以通過實(shí)習(xí)這兩個(gè)接口來創(chuàng)建自定義的方案。

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; }
}

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

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

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

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
                }
            }
        }
    }
}

現(xiàn)在你就可以像下面這樣應(yīng)用自定義的授權(quán)過濾器在控制器級(jí)別或者action級(jí)別。

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

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

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

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

public class BlogModel
{
 [Required]
 [Display(Name = "Title")]
 public string Title { get; set; }
 [AllowHtml]
 [Required]
 [Display(Name = "Description")]
 public string Description { get; set; }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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