如何使用Windows Active Directory身份验证和基于身份的声明?

hly*_*tes 29 authentication claims-based-identity asp.net-identity visual-studio-2015 asp.net-core

问题

我们希望使用Windows Active Directory对用户进行应用程序身份验证.但是,我们不希望使用Active Directory组来管理控制器/视图的授权.

据我所知,没有一种简单的方法可以将AD和基于身份的声明结合起来.

目标

  • 使用本地Active Directory对用户进行身份验证
  • 使用Identity框架来管理声明

尝试(失败)

  • Windows.Owin.Security.ActiveDirectory - Doh.这适用于Azure AD.没有LDAP支持.他们可以将其称为AzureActiveDirectory吗?
  • Windows身份验证 - 使用NTLM或Keberos身份验证时可以.问题始于:i)令牌和索赔都由AD管理,我无法弄清楚如何使用身份声明.
  • LDAP - 但这些似乎迫使我手动进行表单身份验证以使用身份声明?当然必须有一个更简单的方法吗?

任何帮助都不仅仅是值得赞赏的.我已经坚持这个问题很长一段时间了,并且会对这个问题的外部投入表示赞赏.

Sho*_*hoe 20

只需使用用户名和密码命中AD,而不是针对您的数据库进行身份验证

// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindByNameAsync(model.UserName);
        if (user != null && AuthenticateAD(model.UserName, model.Password))
        {
            await SignInAsync(user, model.RememberMe);
            return RedirectToLocal(returnUrl);
        }
        else
        {
            ModelState.AddModelError("", "Invalid username or password.");
        }
    }
    return View(model);
}

public bool AuthenticateAD(string username, string password)
{
    using(var context = new PrincipalContext(ContextType.Domain, "MYDOMAIN"))
    {
        return context.ValidateCredentials(username, password);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在SignInManager存在之前,`SignInAsync`曾经是一个辅助方法.但这个概念是一样的.`PrincipalContext`来自命名空间`System.DirectoryServices.AccountManagement`.在项目中添加对它的引用以使用它. (2认同)

小智 5

在 ASPNET5 (beta6) 上,想法是使用 CookieAuthentication 和 Identity :您需要在 Startup 类中添加:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddAuthorization();
    services.AddIdentity<MyUser, MyRole>()
        .AddUserStore<MyUserStore<MyUser>>()
        .AddRoleStore<MyRoleStore<MyRole>>()
        .AddUserManager<MyUserManager>()
        .AddDefaultTokenProviders();
}
Run Code Online (Sandbox Code Playgroud)

在配置部分添加:

private void ConfigureAuth(IApplicationBuilder app)
{
    // Use Microsoft.AspNet.Identity & Cookie authentication
    app.UseIdentity();
    app.UseCookieAuthentication(options =>
    {
        options.AutomaticAuthentication = true;
        options.LoginPath = new PathString("/App/Login");
    });
}
Run Code Online (Sandbox Code Playgroud)

然后,您将需要实施:

Microsoft.AspNet.Identity.IUserStore
Microsoft.AspNet.Identity.IRoleStore
Microsoft.AspNet.Identity.IUserClaimsPrincipalFactory
Run Code Online (Sandbox Code Playgroud)

并扩展/覆盖:

Microsoft.AspNet.Identity.UserManager
Microsoft.AspNet.Identity.SignInManager
Run Code Online (Sandbox Code Playgroud)

我实际上已经设置了一个示例项目来展示如何做到这一点。 GitHub 链接

我在 beta8 上进行了测试,并且使用一些小型适配器(例如 Context => HttpContext),它也可以工作。


Wil*_*ill 3

上面的解决方案将我推向了一个在 MVC6-Beta3 Identityframework7-Beta3 EntityFramework7-Beta3 上对我有用的方向:

// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    //
    // Check for user existance in Identity Framework
    //
    ApplicationUser applicationUser = await _userManager.FindByNameAsync(model.eID);
    if (applicationUser == null)
    {
        ModelState.AddModelError("", "Invalid username");
        return View(model);
    }

    //
    // Authenticate user credentials against Active Directory
    //
    bool isAuthenticated = await Authentication.ValidateCredentialsAsync(
        _applicationSettings.Options.DomainController, 
        _applicationSettings.Options.DomainControllerSslPort, 
        model.eID, model.Password);
    if (isAuthenticated == false)
    {
        ModelState.AddModelError("", "Invalid username or password.");
        return View(model);
    }

    //
    // Signing the user step 1.
    //
    IdentityResult identityResult 
        = await _userManager.CreateAsync(
            applicationUser, 
            cancellationToken: Context.RequestAborted);

    if(identityResult != IdentityResult.Success)
    {
        foreach (IdentityError error in identityResult.Errors)
        {
            ModelState.AddModelError("", error.Description);
        }
        return View(model);
    }

    //
    // Signing the user step 2.
    //
    await _signInManager.SignInAsync(applicationUser,
        isPersistent: false,
        authenticationMethod:null,
        cancellationToken: Context.RequestAborted);

    return RedirectToLocal(returnUrl);
}
Run Code Online (Sandbox Code Playgroud)

  • “身份验证”是 MVC6 独有的功能吗?目前尚不清楚它应该来自哪里,但它是一个关键部分。 (3认同)