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

发布于 2024-12-02 14:52:05 字数 282 浏览 3 评论 0原文

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

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

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

How can I implement role based custom user authentication in asp.net MVC 3. Consider I have two table UserInfo(UserId, UserName, Password,RoleId) and Role(RoleId, RoleName).

I want to validate user from Database(UserInfo Table) and also want to retrieve roles from that table. And want to use like
[Authorize(Roles="Admin")]

Need your help and idea....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧人 2024-12-09 14:52:05

您可以使用自定义授权属性并将角色存储在身份验证 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);

然后您可以编写一个自定义授权属性,该属性将用于读取身份验证 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"
    };
}

You could use a custom authorize attribute and store the roles in the user data part of the authentication cookie. So for example inside your LogOn method once you have verified the credentials you could retrieve the roles for the given user from your database and store them into the user data:

// 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);

Then you could write a custom authorize attribute which will be used to read the authentication cookie and extract the roles information:

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);
    }
}

Now all that's left is to decorate your controllers/actions with this new attribute:

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

UPDATE:

As requested in the comments section here's how you could override the HandleUnauthorizedRequest method in the custom authorize attribute so that if the user is not authorized to access a given action he is redirected to some error view instead of the login page:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    filterContext.Result = new ViewResult
    {
        ViewName = "~/Views/Shared/Unauthorized.cshtml"
    };
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文