c# - ASP.NET MVC5 自定义 AuthorizeAttribute 未被正确调用

标签 c# asp.net asp.net-mvc asp.net-mvc-5

tl;dr:我的覆盖 AuthorizeAttribute 的 AuthorizeCore 方法的自定义属性未被正确调用 - 导致访问不受限制。

长话短说:我有一个具有四个角色(管理员、调度员、培训师和学生)的 ASP.NET MVC5 应用程序。直到现在我使用内置的

[Authorize("Administrator")]

我的 Controller ( View 和 API)的类和方法的属性,以针对按预期工作的 Active Directory 执行 Windows 身份验证。

现在我想更改属性中角色的硬编码字符串名称并从数据库中获取角色名称,这样就可以通过数据库配置 Active Directory 组名称,同时仍然执行身份验证直接针对 Active Directory。

工作流程:

  1. 方法/ Controller 仅允许角色“管理员”使用。
  2. 从数据库中获取“管理员”Active Directory 组,t.ex。 “域管理员”
  3. 检查当前用户是否是 Active Directory 组“DomainAdmins”的成员。如果是,授予访问权限。

我发现,Authorize 属性需要一个 const 值,所以我决定实现我的自定义

[DynamicAuthorize(Roles = Role.AdministratorRole)]

Role.AdministratorRole 是一个常量字符串。

现在我看到,对于 View Controller ,一切都按预期工作。但是当我的 API Controller 被调用时(例如删除用户),AuthorizeCore(...) 方法被调用。

可能与线程安全或 ASP.NET MVC5 的内部工作方式有关。我还认为 AuthorizeCore(...) 方法中的代码并不重要,因为它甚至没有被调用。

我很感激任何提示或建议。

DynamicAuthorize.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;

namespace Project.Utilities.Attributes
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class DynamicAuthorize : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }

            IPrincipal user = httpContext.User;
            if (!user.Identity.IsAuthenticated)
            {
                return false;
            }

            if (SplitString(Users).Length > 0 && !(SplitString(Users).Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)))
            {
                return false;
            }

            // Role preparation
            List<string> allowedRolesRaw = new List<string>(SplitString(Roles));
            string allowedRolesAd = "";

            // GetRolesActiveDirectoryGroupName(...) loads role names from the database
            allowedRolesRaw.ForEach(rc => allowedRolesAd += DomainMapper.GetRolesActiveDirectoryGroupName(DomainMapper.GetRoleIdFromAttributeName(rc), true) + ", ");

            if (SplitString(Roles).Length > 0 && !(SplitString(allowedRolesAd).Any(user.IsInRole)))
            {
                return false;
            }

            return true;
        }

        internal static string[] SplitString(string original)
        {
            if (String.IsNullOrEmpty(original))
            {
                return new string[0];
            }

            var split = from piece in original.Split(',')
                        let trimmed = piece.Trim()
                        where !String.IsNullOrEmpty(trimmed)
                        select trimmed;
            return split.ToArray();
        }
    }
}

基于:

UsersController.cs(不工作 => 未被调用)

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using Project.Models;
using Project.Utilities.Attributes;

namespace Project.Controllers.api
{
    [DynamicAuthorize(Roles = Role.AdministratorRole)]
    public class UsersController : ApiController
    {
        // Methods in here do not have an attribute
    }
}

ManagementController.cs(似乎在工作 => 总是被调用)

using Project.Utilities.Attributes;
using Hangfire;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Net;
using System.Web.Mvc;
using static Project.Utilities.Attributes.AntiForgeryToken;
using Project.Dtos;
using Project.Mapper;
using Project.ViewModels;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace Project.Controllers
{
    [DynamicAuthorize(Roles = Role.AdministratorRole + ", " + Role.SchedulerRole)]
    public class ManagementController : Controller
    {
        // Methods here do sometimes have an attribute if a specific action is also allowed for different roles
    }
}

最佳答案

您需要为 API 在 System.Web.Http 中覆盖 AuthorizatioAttribute 上的 OnAuthorization 方法。

public virtual void OnAuthorization(HttpActionContext actionContext);

因此,Web API 的过滤器与 MVC 的过滤器不同。 Web API 过滤器位于 System.Web.Http.Filters 命名空间

您可以获得更多详情https://damienbod.com/2014/01/04/web-api-2-using-actionfilterattribute-overrideactionfiltersattribute-and-ioc-injection/

关于c# - ASP.NET MVC5 自定义 AuthorizeAttribute 未被正确调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49687076/

相关文章:

c# - 在分片和主数据库之间使用数据库名称进行跨数据库查询在带有分片的 sql azure 中不起作用

jquery - 使用Jquery表单插件asp.net mvc 3

c# - Windows 7 上的 shcore.dll - 它存在吗?

asp.net - 运行一次请求最好的地方在哪里?

asp.net - 使用 PopupControlExtender 实现右键单击上下文菜单?

asp.net-mvc - 为什么 Entity Framework 不初始化我的导航集合?

javascript - 当 ViewModel 的属性重命名时 Knockout.js 绑定(bind)被破坏

php - 哪个 PHP MVC 项目与 ASP.NET MVC 最相似?

c# - 在 Visual Studio 中隐藏导航栏

c# - 正则表达式来验证逗号分隔的电子邮件地址?