ASP.NET MVC 自定义授权

发布于 2024-08-04 05:06:22 字数 894 浏览 7 评论 0原文

我正在使用 ASP.NET MVC 构建一个 Web 应用程序,该应用程序有两种截然不同的用户类型。我将举一个例子,说一种类型是内容生产者(发布者),另一种类型是内容消费者(订阅者)。

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

我正在考虑将它们与枚举字段(技术上是 int 字段)存储在同一个表中。然后创建一个 CustomAuthorizationAttribute,我将在其中传递该页面所需的 userType。

例如,PublishContent 页面需要 userType == UserType.Publisher,因此只有发布者可以访问它。因此,创建此属性使我可以访问 HttpContextBase,其中包含标准 User 字段(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;
    }
}

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

I am building a web application using ASP.NET MVC that has two very distinct types of users. I'll contrive an example and say that one type is content producers (publishers) and another is content consumers (subscribers).

I am not planning on using the built-in ASP.NET authorization stuff, because the separation of my user types is a dichotomy, you're either a publisher or a subscriber, not both. So, the build-in authorization is more complex than I need. Plus I am planning on using MySQL.

I was thinking about storing them in the same table with an enum field (technically an int field). Then creating a CustomAuthorizationAttribute, where I'd pass in the userType needed for that page.

For example, the PublishContent page would require userType == UserType.Publisher, so only Publishers could access it. So, creating this attribute gives me access to the HttpContextBase, which contains the standard User field (of type IPrincipal). How do I get my UserType field onto this IPrincipal? So, then my attribute would look like:

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

Or does anyone think my entire approach is flawed?

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

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

发布评论

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

评论(1

苏大泽ㄣ 2024-08-11 05:06:22

我仍然会使用内置的 ASP.NET 表单身份验证,但只需根据您的需求进行自定义即可。

因此,您需要让 User 类实现 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;
    }
}

AccountController.cs

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOn(LogOnForm logOnForm)
{
    try
    {
        if (ModelState.IsValid)
        {
            WebUser user = AccountService.GetWebUserFromLogOnForm(logOnForm);

            Response.Cookies.Add(FormsAuth.GetAuthCookie(user, logOnForm.RememberMe));

            return Redirect(logOnForm.ReturnUrl);
        }
    }
    catch (ServiceLayerException ex)
    {
        ex.BindToModelState(ModelState);
    }
    catch
    {
        ModelState.AddModelError("*", "There was server error trying to log on, try again. If your problem persists, please contact us.");
    }

    return View("LogOn", logOnForm);
}

中最后是我的 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
查尔斯

I would still use the built in ASP.NET forms authentication but just customize it to your needs.

So you'll need to get your User class to implement the IPrincipal interface and then write your own custom cookie handling. Then you can simply just use the built in [Authorize] attribute.

Currently I have something similar to the following...

In my 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;
    }
}

AccountController.cs

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOn(LogOnForm logOnForm)
{
    try
    {
        if (ModelState.IsValid)
        {
            WebUser user = AccountService.GetWebUserFromLogOnForm(logOnForm);

            Response.Cookies.Add(FormsAuth.GetAuthCookie(user, logOnForm.RememberMe));

            return Redirect(logOnForm.ReturnUrl);
        }
    }
    catch (ServiceLayerException ex)
    {
        ex.BindToModelState(ModelState);
    }
    catch
    {
        ModelState.AddModelError("*", "There was server error trying to log on, try again. If your problem persists, please contact us.");
    }

    return View("LogOn", logOnForm);
}

And finally my 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
Charles

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文