如何在asp.net MVC 3中实现/创建基于角色的自定义用户身份验证

时间:2011-09-04 06:45:02

标签: asp.net-mvc-3 roles authentication

如何在asp.net MVC 3中实现基于角色的自定义用户身份验证。考虑我有两个表UserInfo(UserId, UserName, Password,RoleId)Role(RoleId, RoleName)

我想从数据库(UserInfo表)验证用户,并且还想从该表中检索角色。并希望使用喜欢 [Authorize(Roles="Admin")]

需要你的帮助和想法......

1 个答案:

答案 0 :(得分:6)

您可以使用自定义授权属性并将角色存储在身份验证Cookie的用户数据部分中。因此,例如,在验证凭据后,在LogOn方法中,您可以从数据库中检索给定用户的角色并将其存储到用户数据中:

// TODO: fetch roles from your database based on the username
var roles = "Admin|SomeRole";
var ticket = new FormsAuthenticationTicket(
    1, 
    username,
    DateTime.Now, 
    DateTime.Now.AddMilliseconds(FormsAuthentication.Timeout.TotalMilliseconds), 
    false, 
    roles
);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
    Domain = FormsAuthentication.CookieDomain,
    HttpOnly = true,
    Secure = FormsAuthentication.RequireSSL,
};

// Emit the authentication cookie which in addition to the username will
// contain the roles in the user data part
Response.AppendCookie(authCookie);

然后你可以编写一个自定义authorize属性,用于读取身份验证cookie并提取角色信息:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext.User.Identity.IsAuthenticated)
        {
            var authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie != null)
            {
                var ticket = FormsAuthentication.Decrypt(authCookie.Value);
                var identity = new GenericIdentity(httpContext.User.Identity.Name);
                var roles = (ticket.UserData ?? string.Empty).Split('|');
                httpContext.User = new GenericPrincipal(identity, roles);
            }
        }

        return base.AuthorizeCore(httpContext);
    }
}

现在剩下的就是使用这个新属性来装饰你的控制器/动作:

[MyAuthorize(Roles = "Admin")]
public ActionResult Foo()
{
    ...
}

更新:

根据评论部分的要求,您可以在自定义授权属性中覆盖HandleUnauthorizedRequest方法,这样,如果用户无权访问给定的操作,则会将其重定向到某个错误视图而不是登录页:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    filterContext.Result = new ViewResult
    {
        ViewName = "~/Views/Shared/Unauthorized.cshtml"
    };
}