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 知多少(八)

本节主要讲解过滤器

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Phoenix的Android之旅

JSONObject 和 JsonObject 的区别

做Java开发经常要用Json来做数据的格式化解析,虽然在Android平台上我们习惯的使用 JSONObject, 但不知道你有没有这样的疑问,我们在impo...

25210
来自专栏一个爱瞎折腾的程序猿

.net core建站踩坑记录

services.AddOptions(); services.Configure<AppSettings>(Configuration...

36720
来自专栏跟着阿笨一起玩NET

winform 窗体实现增删改查(CRUD)窗体基类模式

参考博客下方:http://www.cnblogs.com/wuhuacong/archive/2010/05/31/1748579.html

37420
来自专栏葡萄城控件技术团队

ASP.NET 5系列教程(七)完结篇-解读代码

在本文中,我们将一起查看TodoController 类代码。 [Route] 属性定义了Controller的URL 模板: [Route("api/[con...

22150
来自专栏小特工作室

基于Cef内核的多店铺登录器(含源码)

        公司是做电商的,在速卖通平台上开了若干店铺,每天都需要登录店铺打理,如:发货提交、获取运单号等。多个店铺的情况下,同时使用浏览器就会非常繁琐,如...

354100
来自专栏张善友的专栏

实现WCF和Unity 的集成

Artech 已经写过一篇[原创]WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container...

39080
来自专栏.net core新时代

npoi批量导入实现及相关技巧

  批量导入功能对于大部分后台系统来说都是不可或缺的一部分,常见的场景-基础数据的录入(部门,用户),用批量导入方便快捷。最近项目需要用到批量导入,决定花点时间...

50550
来自专栏.NET开发者社区

一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](九)

前言 童鞋们,大家好 我是专注.NET开发者社区建设的实践者Rector。 首先,为自己间隔了两个星期五再更新本系列文章找个不充分的理由:Rector最近工作,...

29450
来自专栏技术博客

菜菜从零学习WCF九(会话、实例化和并发)

在服务协定上设置System.ServiceModel.ServiceContractAttribute.SessionMode值

10830
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(30)-本地化(多语言)

我们的系统有时要扩展到其他国家,或者地区,需要更多的语言环境,微软提供了一些解决方案,原始我们是用js来控制的,现在不需要了。 我们只要创建简单的资源文件,通过...

34770

扫码关注云+社区

领取腾讯云代金券