Броски авторизации ролей Не удалось установить доверительные отношения между этой рабочей станцией и основным доменом.

Я использую ASP.NET Core 3.1 с проверкой подлинности Windows. Если я использую только [Authorize], все в порядке, однако, если я украсил свой контроллер [Authorize(Roles = "GlobalAdmin")], авторизация не удалась.

Это происходит как в среде разработки на моем локальном компьютере, так и после развертывания в интрасети.

Мне определенно назначены правильные роли, потому что следующее работает нормально:

if(await _userManager.IsInRoleAsync(await _userManager.FindByNameAsync(User.Identity.Name), "GlobalAdmin"))
{
    return View();
}

Но я не хочу делать это для каждого метода в моем контроллере, и я не могу использовать его в конструкторе на базовом контроллере, потому что User.Identity возвращает null в конструкторе.

И используя следующее, var y показывает мне мои правильные роли

var x = await _userManager.FindByNameAsync(User.Identity.Name);
var y = await _userManager.GetRolesAsync(x);

Раньше мне удавалось создать настраиваемое переопределение для атрибута Authorize, и я выполнил свою собственную валидацию роли там, но ядро ​​3.1, похоже, изменило методы, поэтому их нет для переопределения.

Но почему атрибут [Authorize] вообще не работает для моих ролей?

В моем стартапе есть

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentity<IdentityUser, IdentityRole>()
        .AddRoleManager<RoleManager<IdentityRole>>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.Configure<IdentityOptions>(options =>
    {
        options.User.AllowedUserNameCharacters =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.\\";
        options.User.RequireUniqueEmail = true;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("MyConnString")));

    services.AddControllersWithViews();
 }

а также

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
        if (env.IsDevelopment())
        {
            //app.UseMiddleware<Helpers.ErrorHandlingMiddleware>();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseMiddleware<Helpers.ErrorHandlingMiddleware>();
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        app.UseStaticFiles();

        app.UseAuthentication();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

Вся трассировка стека выглядит так:

Win32Exception: доверительные отношения между этой рабочей станцией и основным доменом не удалось.

System.Security.Principal.NTAccount.TranslateToSids (IdentityReferenceCollection sourceAccounts, out bool someFailed)
System.Security.Principal.NTAccount.Translate (IdentityReferenceCollection sourceAccounts, Type targetType, outbool someFailed. .NTAccount.Translate (IdentityReferenceCollection sourceAccounts, Type targetType, bool forceSuccess)
System.Security.Principal.WindowsPrincipal.IsInRole (строковая роль)
Microsoft.AspNetCore.Authorization.Infrastructureplay.Roles_RolesAuthorization строка r)
System.Linq.Enumerable.Any (источник IEnumerable, Func ‹TSource, bool› предикат)
Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement.HandleRequirementAsync (контекст AuthorizationHandlerContext, требование RolesAuthorization) /> Microsoft.AspNetCore.Authorization.AuthorizationHandler.HandleAsync (контекст AuthorizationHandlerContext)
Microsoft.AspNetCore.Authorization .Infrastructure.PassThroughAuthorizationHandler.HandleAsync (контекст AuthorizationHandlerContext)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService.AuthorizeAsync (ClaimsPrincipal пользователь, объектный ресурс, IEnumerable требования)
Microsoft.AuthorizePrincipal. policy, AuthenticateResult authenticationResult, контекст HttpContext, ресурс объекта)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke (контекст HttpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke (контекст HttpContext)


person jamheadart    schedule 05.12.2020    source источник
comment
@CamiloTerevinto готово! Все, что я могу найти в Интернете с основными ошибками, - это люди, которые не могут использовать IsInRole, но IsInRole отлично работает для меня, я просто не понимаю, почему атрибут Authorize не работает.   -  person jamheadart    schedule 05.12.2020
comment
Если вы не получите ответа, позже в тот же день я изучу исходный код, чтобы попытаться найти различия.   -  person Camilo Terevinto    schedule 05.12.2020
comment
В вашем коде атрибут [Authorization(Roles = "GlobalAdmin")], но в документации он указан как [Authorize(Roles = "GlobalAdmin")], вы пробовали это? Роль- авторизация на основе ASP.NET Core   -  person queue    schedule 05.12.2020
comment
@queue извините, это была ошибка, набранная вручную, на самом деле она украшена [Authorize], как и должно быть, я просто набрал Authorization, потому что это пространство имен. Сегодня утром я набрал в Google оба примерно 20 раз, так что я запутался!   -  person jamheadart    schedule 05.12.2020
comment
@CamiloTerevinto Буду очень признателен, если вам удастся обнаружить ошибку! Я уверен, что создавал и использовал эту точную настройку проекта раньше без проблем, но это могло быть с логинами вместо Windows auth   -  person jamheadart    schedule 05.12.2020
comment
Можете ли вы проверить окно вывода? Мне кажется, что когда вы вызываете методы store, вы на самом деле вызываете свою базу данных, а не ActiveDirectory.   -  person Camilo Terevinto    schedule 05.12.2020
comment
Да, я боролся с этим, я понял, что создание ролей в коде использует таблицы идентификаторов Asp.Net в базе данных, когда на самом деле я должен создавать пользователей и роли в IIS? Поэтому, когда я попробовал это, мне показалось, что моя проблема в том, что мой сервер IIS фактически не позволяет мне создавать пользователей и роли (я думаю, это еще один вопрос!). Роли, которые я использую IsInRole, взяты из БД, но [Authorize] должны использовать IIS (в которых нет ни одного определенного)   -  person jamheadart    schedule 06.12.2020
comment
Если вы на самом деле находитесь в домене, вы должны создать там группы безопасности пользователей, если вы не в домене, вы должны создать группы пользователей в своей локальной системе, используя Управление компьютером ›Локальные пользователи и группы.   -  person queue    schedule 06.12.2020
comment
Какое познавательное путешествие у меня было в эти выходные !! В итоге я создал свой собственный атрибут стиля [Authorize], потому что мне намного проще создавать пользователей и роли в базе данных, чем использовать AD. Я пробовал ClaimsTransformation полагаться исключительно на базу данных, используя существующую [Authorize], но мне все равно пришлось бы создавать группы в AD, чтобы она работала из-за ошибки. Так что, в конце концов, проще просто перехватить OnAuthorization метод и полностью игнорировать группы безопасности! : /: /   -  person jamheadart    schedule 07.12.2020


Ответы (1)


TL:DR;

Ошибка

Не удалось установить доверительные отношения между этой рабочей станцией и основным доменом.

System.Security.Principal.NTAccount.TranslateToSids (IdentityReferenceCollection sourceAccounts, из bool someFailed)

просто сводился к группе, не существующей в локальной системе. Как только группа была создана в нужном месте, даже если в ней не было участников, я перестал получать эту конкретную ошибку.

Для разработки мне пришлось создать свою группу в моей локальной системе, как указано в @queue в комментариях. Но это не решило мою долгосрочную проблему - я хотел использовать роли, определенные в базе данных!

Длинное объяснение:

Я не понимал разницы между AspNetIdentity и Authorization / Authentication

Я создал приложение для проверки подлинности Windows по умолчанию и в итоге создал AspNetIdentity таблиц как часть моих первоначальных миграций с первым кодом, чтобы я мог видеть базу данных моих пользователей и мог создать несколько дополнительных таблиц, связанных с ними. Я думал, что они внутренне связаны, но Identity и Authorisation могут существовать друг без друга полностью.

Я использовал AspNetIdentity классы UserManager и RoleManager для создания пользователей и ролей в базе данных, и userManager.IsInRoleAsync(<username>) показал бы все правильные записи ролей.

Я хотел использовать атрибут [Authorize], но я хотел, чтобы он игнорировал Active Directory - похоже, это ошибка для настройки как в dev, так и на моем сервере iis, мне нужно было бы полагаться на более высокие полномочия и беспокоить других людей. Я просто хотел, чтобы он посмотрел на роли базы данных.

Я попытался использовать класс IClaimsTransformation с [Authorize(Roles = "")], который преобразует роли из базы данных в правильное требование для использования при проверке подлинности Windows. В StackOverflow есть несколько примеров этого, но я продолжал получать ту же ошибку; Windows [Authorization] выйдет из строя сразу же, прежде чем она вызовет ClaimsTransformation, если группа, которую вы проверяете, не существует в системе - даже если вы собираетесь игнорировать их.

Комбинации служб в Startup не существовало, чтобы обойти это.

В итоге я использовал то же решение, что и в предыдущих основных приложениях asp.net, но немного другое для 3.1:

Создал свой собственный Атрибут для замены [Авторизовать] для верхней части моих контроллеров

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public class RolesAttribute : TypeFilterAttribute
{
    public RolesAttribute(string roles) : base(typeof(ClaimRequirementFilter))
    {
        Arguments = new object[] { roles };
    }
}

И создал простой класс, который, к счастью, позволяет мне вводить мой ApplicationDbContext, где у меня есть метод, который получает список имен ролей для данного имени пользователя.

public class ClaimRequirementFilter : IAuthorizationFilter
{

    private readonly string _roles;
    private readonly ApplicationDbContext _context;

    public ClaimRequirementFilter(string roles, ApplicationDbContext context)
    {
        _context = context;
        _roles = roles;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {

        List<string> matchingRoles = _context.CheckRoles(context.HttpContext.User.Identity.Name, roles);
        if(matchingRoles.Count == 0) context.Result = new ForbidResult();

    }
}

Внедрение UserManager, возможно, тоже сработает, но с помощью асинхронных методов это испортит метод OnAuthorization, поэтому я придерживался своего контекста приложения, в котором таблицы AspNetIdentity в любом случае легко доступны.

person jamheadart    schedule 07.12.2020