Требуется ли удостоверение ASP.NET Core для приложения в интрасети, использующего проверку подлинности Windows?

Используя проверку подлинности Windows в веб-приложении интрасети, я хочу добиться следующего:

  • Собрать дополнительные атрибуты из AD (имя, номер сотрудника)
  • Собрать дополнительные атрибуты из таблицы базы данных (рабочее время, оплата)
  • Авторизация на основе ролей приложения (не групп AD)
  • Авторизация на основе атрибута AD (есть прямые подчиненные)
  • Пользователь не предоставил имя пользователя / пароль

В моем поиске ответа предполагается, что мне нужно добавить ClaimsTransformation в мое приложение:

Как использовать аутентификацию Windows с пользователями в базе данных

Заполнение настраиваемого утверждения из SQL с проверкой подлинности Windows приложение в .Net Core

Кэширование заявлений в .NET core 2.0

Хотя я не совсем понимаю решение и почему ClaimsTransformation происходит при каждом запросе, поэтому я ищу ответы на следующие вопросы:

  1. Требуется ли удостоверение ASP.NET Core для работы ClaimsTransformation?
  2. Выполняется ли ClaimsTransformation при каждом запросе только с проверкой подлинности Windows или с проверкой подлинности на основе форм?
  3. Должно ли это происходить по каждому запросу?
  4. Кэширование таких утверждений, как GivenName, Surname, кажется простым, но как насчет ролей? Какие шаги необходимо предпринять, чтобы база данных не попадала каждый раз, а роли обновлялись при внесении изменений.
  5. Есть ли более простая альтернатива тому, что я пытаюсь сделать?

person mheptinstall    schedule 10.04.2018    source источник
comment
1. Нет, 2. Каждый запрос. 5. Похоже, что вы можете использовать Windows auth для первоначального входа в систему Identity, выполнить поиск в базе данных и выдать файл cookie Identity для использования в последующих запросах. Этот мир будет более эффективным, чем преобразование требований по каждому запросу.   -  person Tratcher    schedule 10.04.2018
comment
Не могли бы вы указать мне в правильном направлении, как можно реализовать ваше предложение? Я предполагаю, что пользователю нужно будет войти в систему, чтобы создать файл cookie, но не предоставить никаких учетных данных?   -  person mheptinstall    schedule 10.04.2018


Ответы (1)


Эта статья дала мне несколько идей и вот возможное решение.

Контроллеры будут наследовать от базового контроллера, политика которого требует утверждения Authenticated. Когда его нет, он переходит к AccessDeniedPath и молча выполняет вход в систему, добавляя утверждение Authenticated вместе с любыми другими утверждениями. Если оно уже присутствует, появится сообщение «Доступ запрещен».

При создании нового ClaimsIdentity мне пришлось удалить большинство утверждений в исходном удостоверении, поскольку я получал HTTP 400 - неверный запрос (слишком длинный заголовок запроса).

Есть ли очевидные проблемы с этим подходом?

Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.LoginPath = "/Home/Login";
                options.AccessDeniedPath = "/Home/AccessDenied";
            });

        services.AddAuthorization(options =>
        {
            options.AddPolicy("Authenticated",
                policy => policy.RequireClaim("Authenticated"));
            options.AddPolicy("Admin",
                policy => policy.RequireClaim("Admin"));
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();
        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

Контроллер

[Authorize(Policy = "Authenticated")]
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [Authorize(Policy = "Admin")]
    public IActionResult About()
    {
        return View();
    }

    [AllowAnonymous]
    public async Task<IActionResult> Login(string returnUrl)
    {
        var identity = ((ClaimsIdentity)HttpContext.User.Identity);

        var claims = new List<Claim>
        {
            new Claim("Authenticated", "True"),
            new Claim(ClaimTypes.Name,
                identity.FindFirst(c => c.Type == ClaimTypes.Name).Value),
            new Claim(ClaimTypes.PrimarySid,
                identity.FindFirst(c => c.Type == ClaimTypes.PrimarySid).Value)
        };

        var claimsIdentity = new ClaimsIdentity(
            claims,
            identity.AuthenticationType,
            identity.NameClaimType,
            identity.RoleClaimType);

        await HttpContext.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(claimsIdentity),
            new AuthenticationProperties());

        return Redirect(returnUrl);
    }

    [AllowAnonymous]
    public IActionResult AccessDenied(string returnUrl)
    {
        if (User.FindFirst("Authenticated") == null)
            return RedirectToAction("Login", new { returnUrl });

        return View();
    }
}
person mheptinstall    schedule 10.04.2018