ASP.NET MVC自定义授权

ASP.NET MVC自定义授权,asp.net,mysql,asp.net-mvc,authorization,authorize,Asp.net,Mysql,Asp.net Mvc,Authorization,Authorize,我正在使用ASP.NET MVC构建一个web应用程序,它有两种截然不同的用户类型。我将设计一个示例,其中一种类型是内容生产者(出版商),另一种类型是内容消费者(订阅者) 我不打算使用内置的ASP.NET授权工具,因为我的用户类型的分离是一种二分法,你要么是发布者,要么是订阅者,而不是两者兼而有之。因此,内置授权比我需要的更复杂。另外,我计划使用MySQL 我在考虑将它们存储在同一个带有enum字段(技术上是int字段)的表中。然后创建一个CustomAuthorizationAttribute

我正在使用ASP.NET MVC构建一个web应用程序,它有两种截然不同的用户类型。我将设计一个示例,其中一种类型是内容生产者(出版商),另一种类型是内容消费者(订阅者)

我不打算使用内置的ASP.NET授权工具,因为我的用户类型的分离是一种二分法,你要么是发布者,要么是订阅者,而不是两者兼而有之。因此,内置授权比我需要的更复杂。另外,我计划使用MySQL

我在考虑将它们存储在同一个带有enum字段(技术上是int字段)的表中。然后创建一个CustomAuthorizationAttribute,我将在其中传入该页面所需的用户类型

例如,PublishContent页面需要userType==userType.Publisher,因此只有发布者才能访问它。因此,创建此属性使我能够访问HttpContextBase,它包含标准用户字段(类型为IPrincipal)。如何将我的UserType字段放到这个IPrincipal上?那么,我的属性将如下所示:

public class PublisherAuthorizationAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (!httpContext.User.Identity.IsAuthenticated)
            return false;

        if (!httpContext.User.Identity.UserType == UserTypes.Publisher)
            return false;

        return true;
    }
}

或者有人认为我的整个方法有缺陷吗?

我仍然会使用内置的ASP.NET表单身份验证,但只是根据您的需要对其进行自定义

因此,您需要让您的用户类实现IPrincipal接口,然后编写自己的自定义cookie处理。然后,只需使用内置的[Authorize]属性即可

目前,我有一些类似的如下

在我的global.asax中

protected void Application_AuthenticateRequest()
{
    HttpCookie cookie = Request.Cookies.Get(FormsAuthentication.FormsCookieName);
    if (cookie == null)
        return;

    bool isPersistent;
    int webuserid = GetUserId(cookie, out isPersistent);

    //Lets see if the user exists
    var webUserRepository = Kernel.Get<IWebUserRepository>();

    try
    {
        WebUser current = webUserRepository.GetById(webuserid);

        //Refresh the cookie
        var formsAuth = Kernel.Get<IFormsAuthService>();

        Response.Cookies.Add(formsAuth.GetAuthCookie(current, isPersistent));
        Context.User = current;
    }
    catch (Exception ex)
    {
        //TODO: Logging
        RemoveAuthCookieAndRedirectToDefaultPage();
    }
}

private int GetUserId(HttpCookie cookie, out bool isPersistent)
{
    try
    {
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
        isPersistent = ticket.IsPersistent;
        return int.Parse(ticket.UserData);
    }
    catch (Exception ex)
    {
        //TODO: Logging

        RemoveAuthCookieAndRedirectToDefaultPage();
        isPersistent = false;
        return -1;
    }
}
最后,我的FormsAuthService:

public HttpCookie GetAuthCookie(WebUser webUser, bool createPersistentCookie)
{
    var ticket = new FormsAuthenticationTicket(1,
                                               webUser.Email,
                                               DateTime.Now,
                                               DateTime.Now.AddMonths(1),
                                               createPersistentCookie,
                                               webUser.Id.ToString());

    string cookieValue = FormsAuthentication.Encrypt(ticket);

    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue)
                         {
                             Path = "/"
                         };

    if (createPersistentCookie)
        authCookie.Expires = ticket.Expiration;

    return authCookie;
}
HTHs

查尔斯

这将给MVC带来一个不稳定的混乱局面。绝对不是正确的方法。不稳定的混乱?几乎没有。这是非常短视的说法。
AccountService
FormsAuth
服务都是注入
AccountController
的接口,使其完全可测试。其他一切都依赖于FormsAuthentication(你还怎么做formsauth?),正如你应该知道的,这是众所周知的难以测试的——正如默认的ASP.NET MVC项目所指出的那样。当然,您可以提取对服务的FormsAuthentication调用,但考虑到对服务的调用在哪里,这真的能实现什么?
public HttpCookie GetAuthCookie(WebUser webUser, bool createPersistentCookie)
{
    var ticket = new FormsAuthenticationTicket(1,
                                               webUser.Email,
                                               DateTime.Now,
                                               DateTime.Now.AddMonths(1),
                                               createPersistentCookie,
                                               webUser.Id.ToString());

    string cookieValue = FormsAuthentication.Encrypt(ticket);

    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue)
                         {
                             Path = "/"
                         };

    if (createPersistentCookie)
        authCookie.Expires = ticket.Expiration;

    return authCookie;
}