.Net MVC4 被坑心得(七)filter 身份验证

今天使用filter来做身份验证。

filter本质也是attribute,需要继承自Attribute类,并指定作用范围。但是在mvc中,针对controller和action的filter,一般不直接继承自Attribute,而是继承自FilterAttribute或者其继承类。

mvc4中实现了验证的特性,AuthorizeAttribute,实现了默认的身份验证。但是这个身份验证,是使用默认的数据连接,不能满足我们的实际要求。我们需要针对自己的系统,创建满足系统健全条件的身份验证。

查看此特性的定义如下:

// 摘要://表示一个特性,该特性用于限制调用方对操作方法的访问。[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter{// 摘要://初始化 System.Web.Mvc.AuthorizeAttribute 类的新实例。public AuthorizeAttribute();// 摘要://获取或设置用户角色。//// 返回结果://用户角色。public string Roles { get; set; }//// 摘要://获取此特性的唯一标识符。//// 返回结果://此特性的唯一标识符。public override object TypeId { get; }//// 摘要://获取或设置授权用户。//// 返回结果://授权用户。public string Users { get; set; }// 摘要://重写时,提供一个入口点用于进行自定义授权检查。//// 参数:// httpContext://HTTP 上下文,它封装有关单个 HTTP 请求的所有 HTTP 特定的信息。//// 返回结果://如果用户已经过授权,则为 true;否则为 false。//// 异常:// System.ArgumentNullException://httpContext 参数为 null。protected virtual bool AuthorizeCore(HttpContextBase httpContext);//// 摘要://处理未能授权的 HTTP 请求。//// 参数:// filterContext://封装有关使用 System.Web.Mvc.AuthorizeAttribute 的信息。filterContext 对象包括控制器、HTTP 上下文、请求上下文、操作结果和路由数据。protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext);//// 摘要://在过程请求授权时调用。//// 参数:// filterContext://筛选器上下文,它封装有关使用 System.Web.Mvc.AuthorizeAttribute 的信息。//// 异常:// System.ArgumentNullException://filterContext 参数为 null。public virtual void OnAuthorization(AuthorizationContext filterContext);//// 摘要://在缓存模块请求授权时调用。//// 参数:// httpContext://HTTP 上下文,它封装有关单个 HTTP 请求的所有 HTTP 特定的信息。//// 返回结果://对验证状态的引用。//// 异常:// System.ArgumentNullException://httpContext 参数为 null。protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext);} 他继承自FilterAttribute并实现了IAuthorizationFilter接口。IAuthorizationFilter接口很简单,只有一个OnAuthorization方法,就是身份验证的主题函数。实现IAuthorizationFilter必须实现该方法。

AuthorizeAttribute特性实现了OnAuthorization方法,并将其声明为虚函数,理论上说,只需重写OnAuthorization方法,即可实现验证。但是如果那样,何必从AuthorizeAttribute继承,,直接写一个特性继承自FilterAttribute,和IAuthorizationFilter接口就好了,又轻量。

AuthorizeAttribute提供了3个属性和4个方法,4个方法全都是虚函数。我们重点关注AuthorizeCore和HandleUnauthorizedRequest。重载AuthorizeCore方法,实现判断用户是否合法,并返回bool,并重载HandleUnauthorizedRequest实现AuthorizeCore返回false时的处理。

具体代码:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]public class CheckAccessAttribute : AuthorizeAttribute{protected override bool AuthorizeCore(HttpContextBase httpContext){return Access.CheckCookiesVal(httpContext.Request.Cookies);}protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext){filterContext.Result = new HttpStatusCodeResult(403);}} 若用[CheckAccess]修饰了controller,下面的action可以使用[AllowAnonymous]来忽略验证。

其中,Access.CheckCookiesVal()是自己定义的用于验证的方法,具体定义如下:

/// <summary>/// 登陆和身份验证具体实现/// </summary>public class Access{/// <summary>/// 默认密钥/// </summary>private const string KEY = "!@#$Q";/// <summary>/// 获取验证码/// </summary>/// <param name="userID">用户id</param>/// <param name="key">密钥</param>/// <returns>验证码</returns>private static string GenCookieValStr(string userID, string key){string source = key + "!!?" + userID + "USB";string valStr = Encrypt(source);return valStr;}/// <summary>/// 验证cookie/// </summary>/// <param name="cookies">传入cookie</param>/// <param name="key">密钥</param>/// <returns>是否通过验证</returns>public static bool CheckCookiesVal(HttpCookieCollection cookies, string key = KEY){try{return (cookies["val"].Value == GenCookieValStr(cookies["admin_id"].Value, key));}catch{return false;}}/// <summary>/// 设置cookie(登陆调用)/// </summary>/// <param name="cookies">传入cookie</param>/// <param name="userID">用户id</param>/// <param name="key">密钥</param>public static void SetCookies(HttpCookieCollection cookies, string userID, string key = KEY){HttpCookie cookie = new HttpCookie("admin_id", userID);cookie.Expires = DateTime.Now.AddDays(1);cookies.Add(cookie);cookie = new HttpCookie("val", GenCookieValStr(userID, key));cookie.Expires = DateTime.Now.AddDays(1);cookies.Add(cookie);}/// <summary>/// MD5编码/// </summary>/// <param name="strPwd">待编码字串</param>/// <returns>编码结果</returns>static public string Encrypt(string strPwd){MD5 md5 = new MD5CryptoServiceProvider();byte[] data = System.Text.Encoding.UTF8.GetBytes(strPwd);//将字符编码为一个字节序列byte[] md5data = md5.ComputeHash(data);//计算data字节数组的哈希值md5.Clear();//输出为字符串StringBuilder sb = new StringBuilder();for (int i = 0; i < md5data.Length; i++){sb.Append(md5data[i].ToString("x").PadLeft(2, ‘0’));}return sb.ToString();}}

那段雨骤风狂。人生之旅本就是风雨兼程,是要说曾经拥有,

.Net MVC4 被坑心得(七)filter 身份验证

相关文章:

你感兴趣的文章:

标签云: