首页 > 解决方案 > 具有 Windows 身份验证和自定义属性的 .Net Core 2.2

问题描述

我们有一个使用 Windows 和匿名身份验证的 .Net Core 2.2 WebApi。我们希望根据用户 AD 组限制对控制器/方法的访问。当我们从 Development 转到 Staging 再到 Production 时,我们不想更改 [Authorize(Roles="XXX")] 组。我们的解决方案是以某种方式将授权角色绑定到应用设置,而不是在我们在环境之间移动时允许我们的 DevOps 管道转换。

我们尝试了以下实现:我们将密钥添加到我们的 appsettings.json

    "Permissions": {
    "Group1": {
        "Admin": "Admin-Dev",
        "User": "User-Dev"
    },
    "Group2": {
        "Admin": "Admin-Dev2",
        "User": "User-Dev2"
    }}

然后我们创建了一个类来阅读该部分:

 public class AuthorizationConfiguration
{
    public string Group1 { get; set; }
    public string Group2 { get; set; }


}
public class AuthorizationConfigurationSection
{
    public string Admin { get; set; }
    public string User { get; set; }
}

并将其设置在 startup.cs

 services.Configure<AuthorizationConfiguration>(Configuration.GetSection("Permissions"));

现在我的问题是当我将授权属性添加到我的控制器时,我的 AuthorizationAttribute 需要访问 IConfig。

    public class Authorization : AuthorizeAttribute, IAuthorizationFilter
{
    private readonly AuthorizationConfiguration _permissonNames;

    public Authorization(IOptions<AuthorizationConfiguration> permissonNames)
    {
        _permissonNames = permissonNames.Value;
    }

    public string[] Permissions { get; set; } //Permission string to get from controller

    public void OnAuthorization(AuthorizationFilterContext context)
    {

        if (Permissions == null || Permissions.Length ==0)
        {   
            context.Result = new UnauthorizedResult();
            return;
        }

        if(Permissions.Any(perm => IsInRole(perm)))
        {
            return;
        }

        context.Result = new UnauthorizedResult();
        return;
    }

    private bool IsInRole(string perm)
    {
        var groupName = GetPropertyValue(_permissonNames, perm);
        return true;
    }
    private string GetPropertyValue(object o, string path)
    {
        var propertyNames = path.Split('.');
        var value = o.GetType().GetProperty(propertyNames[0]).GetValue(o, null);

        if (propertyNames.Length == 1 || value == null)
            return value.ToString();
        else
        {
            return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
        }
    }
}

我无法使用该属性而不会收到错误“没有给出与'Authorization.Authorization(IOptions)'所需的正式参数'permissionNames'相对应的参数

 [Authorize]
[Authorization(Permissions = new string[] {AuthorizationKeys.Admin,AuthorizationKeys.Group1,
    AuthorizationKeys.Group2})]
[Route("api/[controller]")]
[ApiController]

标签: asp.net-coreactive-directorywindows-authentication

解决方案


您的代码中有很多问题。首先,您应该修改AuthorizationConfiguration以从以下位置获取正确的AuthorizationConfigurationSectionappsettings.json

public class AuthorizationConfiguration
{

    public AuthorizationConfigurationSection Group1 { get; set; }
    public AuthorizationConfigurationSection Group2 { get; set; }


}
public class AuthorizationConfigurationSection
{
    public string Admin { get; set; }
    public string User { get; set; }
}

然后修改Authorization类以接受string[]来自您的属性的 action 传递:

public Authorization(string[] values)
{
    Permissions = values;
}

public Authorization() : base()
{
}

要阅读 AuthorizationConfiguration 您可以通过HttpContext.RequestServices within过滤器解决它AuthorizationFilterContext

public void OnAuthorization(AuthorizationFilterContext context)
{
    var  _permissonNames = context.HttpContext.RequestServices.GetService<IOptions<AuthorizationConfiguration>>().Value;

    if (Permissions == null || Permissions.Length == 0)
    {
        context.Result = new UnauthorizedResult();
        return;
    }

    if (Permissions.Any(perm => IsInRole(perm, _permissonNames)))
    {
        return;
    }

    context.Result = new UnauthorizedResult();
    return;
}

还要修改你的IsInRole方法:

private bool IsInRole(string perm , AuthorizationConfiguration _permissonNames)
{

    var groupName = GetPropertyValue(_permissonNames, perm);
    return true;
}

推荐阅读