通过数据注释进行身份验证和授权

Authentication & Authorization via Data Annotation

我有一个数据库 table,其中包含应允许对我的应用程序进行一般访问的所有用户。除此之外,还有一个名为 IsAdministrator 的 bool 列,如果为真,则允许该用户访问特定的 actions/views,例如创建新用户.. 删除现有的.. 等..

我的目标是创建一种方法,以便如果用户在不是管理员的情况下尝试访问创建 action/view,它会 returns 他们到错误视图页面。

我知道我可以做这样的事情:

    public ActionResult Personnel()
    {
        // get user who is logged in
        var personLoggedIn = User.Identity.Name.Split('\')[1]; // Intranet application.. so the domain name comes before the username hence the split

        if(_context.UserTable.Single(x => x.UserLogon == personLoggedIn).IsAdministrator == false)
        {
            return View("Error");
        }

        // more code below
    }

我想知道是否可以不将其复制并粘贴到每个不同的 actionresult 中。我可以将其放入数据注释中并用该数据注释装饰每个不同的 actionresult 吗?

更新

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using AuthorizeAttribute = System.Web.Http.AuthorizeAttribute;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AdministratorsOnly : AuthorizeAttribute
{
    public AdministratorsOnly() { }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {

        var personLoggedIn = HttpContext.Current.User.Identity.Name.Split('\')[1];

        using (var _context = new ConnectionStringName())
        {
            if (_context.UserTable.Single(x => x.UserLogon == personLoggedIn).IsAdministrator == false)
            {
                filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
        }


        base.OnAuthorization(filterContext);
    }
}

按照这些思路应该可以做到:

public class CustomAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result = new RedirectResult("~/Error"); //Change "~/Error" to be the path to your error view
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var personLoggedIn = filterContext.HttpContext.User.Identity.Name.Split('\')[1];
        if (_context.UserTable.Single(x => x.UserLogon == personLoggedIn).IsAdministrator == false)
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            this.HandleUnauthorizedRequest(filterContext);
        }
    }
}

那么你会在相关的 methods/classes 之前使用 [CustomAuthorize]。此外,您需要确保初始化 _context 变量。

为什么不是 AuthorizeAttribute

这样,所有 对控制器的请求都必须通过 OnAuthorization 方法。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AdminOnlyAttribute : AuthorizeAttribute 
{
    public AdminOnlyAttribute(){

    }

    public override void OnAuthorization(AuthorizationContext filterContext) 
    {
         //Here you will to figure out to 
         //have to access your Context with some DependencyResolver

         //Exemple
         var _context = ISomeInterface.ReturnCurrentContext();

         var personLoggedIn = User.Identity.Name.Split('\')[1]; // Intranet application.. so the domain name comes before the username hence the split

         if(_context.UserTable.Single(x => x.UserLogon == personLoggedIn).IsAdministrator == false)
         {
            filterContext.Result = new RedirectResult("~/PathToErrorView")
            //Or even
            filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, "You don't have Access")
         }

         base.OnAuthorization(filterContext);
    }         
}

覆盖 OnAuthorization 方法,它会在您的控制器上发出的所有请求上调用

然后像这样使用:

[AdminOnly]
public class MyController {
    [...]