zoukankan      html  css  js  c++  java
  • ASP.NET MVC3 Custom FormAuthorize

    我们开发web系统,用户身份验证是最常见不过的。最简单的办法就是定一个基类,基类里面有判断Cookie或Session是否存在,然后决定是否跳转。今天就利用MVC的特性来一个不一样的验证方式。

     

    1. public class CustomAuthorizeAttribute : AuthorizeAttribute  
    2. {  
    3.     protected override bool AuthorizeCore(HttpContextBase httpContext)  
    4.     {  
    5.         UserIdentity user = WebUtility.GetIdentity(httpContext);  
    6.         if (user != null)  
    7.         {  
    8.             httpContext.User = new UserPrincipal(WebUtility.GetIdentity(httpContext));  
    9.         }  
    10.   
    11.         return user != null;  
    12.     }  
    13.   
    14. }  

    这是自定义的验证机制,重写了系统自带的验证核心逻辑,下面是系统自带的逻辑:

    1. protected virtual bool AuthorizeCore(HttpContextBase httpContext)  
    2. {  
    3.     if (httpContext == null)  
    4.     {  
    5.         throw new ArgumentNullException("httpContext");  
    6.     }  
    7.     IPrincipal user = httpContext.User;  
    8.     return user.Identity.IsAuthenticated && (this._usersSplit.Length <= 0 || this._usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) && (this._rolesSplit.Length <= 0 || this._rolesSplit.Any(new Func<stringbool>(user.IsInRole)));  
    9. }  

    可以看出,验证都是用httpContext.User属性来判断,所以我们对登录、退出和获取用户信息都通过httpContext.User属性就行了。从MVC的示例中我们也可以发现确实如此,看看MVC3的Views里的_LogOnPartial.cshtml的代码:

    1. @if(Request.IsAuthenticated) {  
    2.     <text>Welcome <strong>@User.Identity.Name</strong>!  
    3.     [ @Html.ActionLink("Log Off", "LogOff", "Account") ]</text>  
    4. }  
    5. else {  
    6.     @:[ @Html.ActionLink("Log On", "LogOn", "Account") ]  
    7. }  

    那么现在再看我们刚才重写的验证逻辑,就大致明白了。首先通过一个外部的逻辑获取User,如果没有User说明没有登录,否则就给User赋值,标记登录了。
    再看我们是如何获取这个User的

    public static UserIdentity GetIdentity(HttpContextBase context)
    {
    	var user = GetUser(context);
    	return new UserIdentity(user);
    }
    
    public static User GetUser(HttpContextBase httpContext)  
    {  
        var user = httpContext.Request.Cookies[COOKIE_NAME_KEY];  //明文 比如用的userId
        var info = httpContext.Request.Cookies[COOKIE_INFO_KEY];  //密文
        if (user == null || info == null || !info.Value.DESDecrypt(DES_KEY).Contains(user.Value))  //解密后不一致,说明无效
        {  
            return null;  
        }  
      
        return new User{UserID = int.parse(user.value)};
    }  

    这就很易懂了,也是通过的cookie对用户资料做的存储。
    httpContext.User是IPrincipal类型,所以我们要自定义一个UserPrincipal类:

     

    public class UserPrincipal : IPrincipal
    {
    	public IIdentity Identity { get; private set; }
    
    	public UserPrincipal(IIdentity identity)
    	{
    		this.Identity = identity;
    	}
    
    	public bool IsInRole(string role)
    	{
    		throw new NotSupportedException();
    	}
    }

    似乎UserPrincipal并没有什么内容,而真证的数据存在Identity属性里,所以还需要定义一个UserIdentity类,来满足UserPrincipal。所以从最上面的代码可以看出WebUtility.GetIdentity(httpContext)返回的就是一个UserIdentity实例。

    1. public class UserIdentity : IIdentity  
    2. {  
    3.     public UserIdentity(User user)//此User就是从Cookie解密出来实例化的User
    4.     {  
    5.         User = user;  
    6.     }  
    7.   
    8.     public User User { getprivate set; }  
    9.   
    10.     public string Name  
    11.     {  
    12.         get { return User == null ? string.Empty : User.UserName; }  
    13.     }  
    14.   
    15.     public string AuthenticationType  
    16.     {  
    17.         get { return "maddemon"; }  
    18.     }  
    19.   
    20.     public bool IsAuthenticated  
    21.     {  
    22.         get { return User != null; }  
    23.     }  
    24. }  

    好了,整个验证核心需要的东西我们都准备好了,还差一个最重要的东西就是我们登录的时候需要写cookie,退出的时候需要清除cookie。

    1. public static void SetAuthorizeCookie(HttpContextBase httpContext, User user)  
    2. {  
    3.     httpContext.Response.SetCookie(new HttpCookie(COOKIE_NAME_KEY, user.UserName));  
    4.     httpContext.Response.SetCookie(new HttpCookie(COOKIE_INFO_KEY, (user.UserName + "|" + user.Role).DESEncrypt(DES_KEY)));  
    5. }  
    6.   
    7. public static void RemoveAuthorizeCookie(HttpContextBase httpContext)  
    8. {  
    9.     httpContext.Response.SetCookie(new HttpCookie(COOKIE_NAME_KEY, null) { Expires = DateTime.Now.AddDays(-1) });  
    10.     httpContext.Response.SetCookie(new HttpCookie(COOKIE_INFO_KEY, null) { Expires = DateTime.Now.AddDays(-1) });  
    11. }  

    这样一套下来,需要登录的Controller或Action,我们只需要加上一个[CustomAuthorize]属性就可以,如果没有登录就会自动跳转到config里配置的登录页。是不是很不方便啊? 方便吗?不方便吗? 方便吗?不方便吗? 方便吗?不方便吗?是不是啊 哈哈

    1. <authentication mode="Forms">  
    2.   <forms loginUrl="~/Account/LogOn" timeout="2880" />  
    3. </authentication>  
  • 相关阅读:
    Extjs面板和布局初探
    XAMPP下apache部署网站,多个虚拟机(空间)配置
    安全配置织梦系统初探参考[转载]
    windows系统如何真正隐藏文件夹[转载]
    Siamese-RPN论文阅读
    线段树求和
    算法要点随记
    map使用示例
    算法准备之c++ sort使用示例
    编程要点随记
  • 原文地址:https://www.cnblogs.com/mad/p/ASP_NET_MVC3_Custom_FormAuthorize.html
Copyright © 2011-2022 走看看