如何在asp.net MVC 3中实现基于角色的自定义用户身份验证。考虑我有两个表UserInfo(UserId, UserName, Password,RoleId)
和Role(RoleId, RoleName)
。
我想从数据库(UserInfo
表)验证用户,并且还想从该表中检索角色。并希望使用喜欢
[Authorize(Roles="Admin")]
需要你的帮助和想法......
答案 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"
};
}