【发布时间】:2018-04-06 06:54:15
【问题描述】:
tl;dr:我的覆盖 AuthorizeAttribute 的 AuthorizeCore 方法的自定义属性没有被正确调用 - 导致访问不受限制。
长话短说:我有一个 ASP.NET MVC5 应用程序,它有四个角色(管理员、调度员、培训师和学生)。到目前为止,我使用的是内置的
[Authorize("Administrator")]
我的控制器(视图和 API)的类和方法的属性,以针对按预期工作的 Active Directory 执行 Windows 身份验证。
现在我想更改属性中角色的硬编码字符串名称并从数据库中获取角色名称,以便可以通过数据库配置 Active Directory 组名称,同时仍然执行身份验证直接针对 Active Directory。
工作流程:
- 方法/控制器仅适用于“管理员”角色。
- 从数据库中获取“管理员”Active Directory 组,t.ex。 “域管理员”
- 检查当前用户是否是 Active Directory 组“DomainAdmins”的成员。如果是,请授予访问权限。
我发现 Authorize 属性需要一个 const 值,所以我决定实现我的自定义
[DynamicAuthorize(Roles = Role.AdministratorRole)]
Role.AdministratorRole 是一个常量字符串。
现在我看到,对于视图控制器,一切都按预期工作。但是当我的 API 控制器被调用(例如删除用户)时,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();
}
}
}
基于:
- https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/AuthorizeAttribute.cs
- https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http/AuthorizeAttribute.cs
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
}
}
【问题讨论】:
-
web-api 的
AuthorizeAttribute位于System.Web.Http命名空间中,并且与位于System.Web.Mvc命名空间(您正在使用的那个)中的mvc 的AuthorizeAttribute不兼容 -
谢谢,确实是这个问题!我在问题中添加了我的解决方案。
-
问题中没有答案(我已回滚您的更改)
-
哦,抱歉,我刚刚重新编辑并想知道为什么更改会还原。我应该发帖回答新帖子吗?
-
这是一个问答网站。再次回答(解决方案)不要进入问题。我再次回滚了您的更改。如果您想发布自己的答案,请随时这样做。
标签: c# asp.net asp.net-mvc asp.net-mvc-5