转自:http://blog.csdn.net/kenshincui/article/details/5559508
MVC自带的ActionFilter
在Asp.Net WebForm的中要做到身份认证微软为我们提供了三种方式,其中最常用的就是我们的Form认证,需要配置相应的信息。例如下面的配置信息:
- <authentication mode="Forms">
- <forms loginUrl="Login.aspx" defaultUrl="Default.aspx" protection="All" />
- </authentication>
- <authorization>
- <deny users="?"/>
- <allow users="*"/>
- </authorization>
说明我们登录页面是Login.aspx,登录成功后的默认页面是Default.aspx,而我们用户信息采用验证和加密两种方式。而且最重要的 是我们要写好授权方式(下面的授权一定要写否则只说明使用Forms认证然后设置相关属性是没有用的),拒绝所有匿名用户,只有登录用户可以正常访问。这 样之后我们设置点击登录按钮将用户名写进cookie(也就是执行FormsAuthentication.SetAuthCookie(name, false);)就可以了。
在Asp.Net MVC中我们同样可以使用Forms认证,但是如果你按照WebForm中的做法去做就不行了。例如你这样配置信息:
- <authentication mode="Forms">
- <forms loginUrl="~/Account/Login" defaultUrl="~/Home/Index" protection="All"/>
- </authentication>
- <authorization>
- <deny users="?"/>
- <allow users="*"/>
- </authorization>
你在Login.aspx中设置登录来触发AccountController中的Logon来登录,其中Logon代码:
- public ActionResult Logon(string name,string password)
- {
- if (name == "jianxin160" && password == "160796")
- {
- FormsAuthentication.SetAuthCookie(name, false);
- return Redirect("~/Home/Index");
- }
- else
- {
- return Redirect("/");
- }
- }
这样的操作之后你会发现你的Logon是不会执行的。原因是什么呢?怎么同样的设置为什么到了MVC中就不行了?原因就是二者机制不同,因为你设置的授权方式让Logon无法访问了。那么我们怎么来做呢?
其实在Asp.Net MVC中我们有更好的方式来做这一切,我们不需要授权方式,也就是说我们的配置信息像这样:
- <authentication mode="Forms">
- <forms loginUrl="~/Account/Login" defaultUrl="~/Home/Index" protection="All"/>
- </authentication>
不需要说明匿名用户不能登录等。当然了,你会发现仅仅就这样做肯定不行的我们还要换一种方式告诉系统哪些是需要登录才能访问的。你或许 想,o(︶︿︶)o 唉,那太麻烦了吧。其实不是这样的,很简单,我们只需要在需要认证的Action上标记[Authorize]就可以了。例如我在Home文件夹中有两个 页面Index和Home,我现在想让Index经过认证才能访问,而Home不需要,那么只需要给Index这个Action标记 [Authorize],也就是:
- [Authorize]
- public ActionResult Index()
- {
- return View();
- }
- public ActionResult Home()
- {
- return View();
- }
这样Index就必须登录之后才能访问,而Home是不需要登录的。如果你需要进行角色授权那么您就可以在标记Authorize的时候指明角色 (例如[Authorize(Role=Administrators)] ),不过您这是就必须使用微软给我们提供的Membership机制了,因为您的Role不可能是平白无故有的,而是存在于对应的数据库中的,这个我在另 一篇博客中提到过就不多说了。
自定义ActionFilter
有时候这样的认证或许您还不能够满足,或者说您觉得不够灵活,那么也没有关系,Asp.Net MVC是允许您自定义ActionFilter的。例如我现在自定义身份认证:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using System.Web.Security;
- namespace FormFormsAuthenticationMvc
- {
- public class RequiresAuthenticationAttribute:ActionFilterAttribute
- {
- public override void OnActionExecuting(ActionExecutingContext filterContext)
- {
- if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
- {
- string returnUrl = filterContext.HttpContext.Request.Url.AbsolutePath;
- string redirectUrl = string.Format("?ReturnUrl={0}", returnUrl);
- string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
- filterContext.HttpContext.Response.Redirect(loginUrl, true);
- }
- }
- }
- }
如果需要进行用户管理,我再定义角色相关的Filter:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using System.Web.Security;
- namespace MvcApplication1.MyClass
- {
- public class RequiresRoleAttribute:ActionFilterAttribute
- {
- public string Role { get; set; }
- public override void OnActionExecuting(ActionExecutingContext filterContext)
- {
- if (!string.IsNullOrEmpty(Role))
- {
- if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
- {
- string returnUrl = filterContext.HttpContext.Request.Url.AbsolutePath;
- string redirectUrl = string.Format("?ReturnUrl={0}", returnUrl);
- string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
- filterContext.HttpContext.Response.Redirect(loginUrl, true);
- }
- else
- {
- bool isAuthenticated = filterContext.HttpContext.User.IsInRole(Role);
- if (!isAuthenticated)
- {
- throw new UnauthorizedAccessException("You have no right to view the page!");
- }
- }
- }
- else
- {
- throw new InvalidOperationException("No Role Specified!");
- }
- }
- }
- }
其实您会发现上面两个Attribute其实MVC自带的Authorized已经解决了,这里主要告诉大家如果有需要您是可以扩展的。
好了,今天就到这里吧!源代码下载:FormFormsAuthenticationMvc