. Net Core 2.2 с Windows аутентификацией и пользовательским атрибутом - PullRequest
0 голосов
/ 14 марта 2020

У нас есть. Net Core 2.2 WebApi, который использует Windows и анонимную аутентификацию. Мы хотим ограничить доступ к контроллерам / методам на основе группы пользователей AD. Мы не хотим менять группу [Authorize (Roles = "XXX")], когда мы go переходим с разработки на этап подготовки к производству. Наше решение состоит в том, чтобы каким-то образом связать санкционированную роль с настройками приложений, а затем позволить преобразованию нашего конвейера DevOps при переходе между средами.

Мы попробовали следующую реализацию: Мы добавили ключи в наши настройки приложений. 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] + ".", ""));
        }
    }
}

Я не могу использовать атрибут, не получив сообщение об ошибке "Не задан аргумент, который соответствует необходимому формальному параметру "missionNames" из "Authorization.Authorization (IOptions)" *

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

1 Ответ

0 голосов
/ 16 марта 2020

В ваших кодах много проблем. Во-первых, вы должны изменить AuthorizationConfiguration, чтобы получить правильные AuthorizationConfigurationSection значения из appsettings.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[], которые передаются из вашего атрибута на действие :

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

public Authorization() : base()
{
}

Чтобы прочитать конфигурацию авторизации, вы можете разрешить ее через 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;
}
...