webentwicklung-frage-antwort-db.com.de

Wie verwende ich Windows Active Directory-Authentifizierung und identitätsbasierte Ansprüche?

Problem

Wir möchten Windows Active Directory verwenden, um einen Benutzer in der Anwendung zu authentifizieren. Wir möchten jedoch keine Active Directory-Gruppen zum Verwalten der Autorisierung von Controllern/Ansichten verwenden.

Soweit ich weiß, gibt es keine einfache Möglichkeit, AD- und identitätsbasierte Ansprüche zu heiraten.

Tore

  • Authentifizieren Sie Benutzer mit lokalem Active Directory
  • Verwenden Sie das Identity Framework, um Ansprüche zu verwalten

Versuche (Scheitern)

  • Windows.Owin.Security.ActiveDirectory - Doh. Dies ist für Azure AD. Keine LDAP-Unterstützung. Könnten sie es stattdessen AzureActiveDirectory genannt haben?
  • Windows-Authentifizierung - Dies ist bei NTLM- oder Keberos-Authentifizierung in Ordnung. Die Probleme beginnen mit: i) Token und Ansprüche werden alle von AD verwaltet, und ich kann nicht herausfinden, wie Identitätsansprüche damit verwendet werden.
  • LDAP - Aber dies scheint mich zu zwingen, die Formularauthentifizierung manuell durchzuführen, um Identitätsansprüche zu verwenden? Sicherlich muss es einen einfacheren Weg geben?

Jede Hilfe wäre mehr als dankbar. Ich habe mich lange mit diesem Problem befasst und würde mich über Beiträge von außen zu diesem Thema freuen.

29
hlyates

Mit Ihrer obigen Lösung bin ich in eine Richtung gegangen, die für mich in MVC6-Beta3 Identityframework7-Beta3 EntityFramework7-Beta3 funktioniert hat:

// 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);
}
2
Will

Drücken Sie einfach AD mit dem Benutzernamen und dem Passwort, anstatt sich bei Ihrer Datenbank zu authentifizieren

// 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);
    }
}
20
Shoe

In ASPNET5 (Beta6) sollten Sie CookieAuthentication und Identity verwenden: Fügen Sie Folgendes in Ihre Startup-Klasse ein:

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

Fügen Sie im Abschnitt configure Folgendes hinzu:

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");
    });
}

Dann müssen Sie Folgendes implementieren:

Microsoft.AspNet.Identity.IUserStore
Microsoft.AspNet.Identity.IRoleStore
Microsoft.AspNet.Identity.IUserClaimsPrincipalFactory

und verlängern/überschreiben:

Microsoft.AspNet.Identity.UserManager
Microsoft.AspNet.Identity.SignInManager

Ich habe tatsächlich ein Beispielprojekt eingerichtet, um zu zeigen, wie dies getan werden kann. GitHub Link .

Ich habe es auf der Beta8 getestet und mit ein paar kleinen Anpassungen (wie Context => HttpContext) hat es auch funktioniert.

4
jesblit

Sie könnten ClaimTransformation verwenden. Ich habe es heute Nachmittag mit dem folgenden Artikel und Code zum Laufen gebracht. Ich greife auf eine Anwendung mit Fensterauthentifizierung zu und füge dann Ansprüche hinzu, die auf Berechtigungen basieren, die in einer SQL-Datenbank gespeichert sind. Dies ist ein guter Artikel, der Ihnen helfen sollte.

https://github.com/aspnet/Security/issues/86

In Summe ...

services.AddScoped<IClaimsTransformer, ClaimsTransformer>();

app.UseClaimsTransformation(async (context) =>
{
IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return await transformer.TransformAsync(context);
});

public class ClaimsTransformer : IClaimsTransformer
    {
        private readonly DbContext _context;

        public ClaimsTransformer(DbContext dbContext)
        {
            _context = dbContext;
        }
        public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
        {

            System.Security.Principal.WindowsIdentity windowsIdentity = null;

            foreach (var i in context.Principal.Identities)
            {
                //windows token
                if (i.GetType() == typeof(System.Security.Principal.WindowsIdentity))
                {
                    windowsIdentity = (System.Security.Principal.WindowsIdentity)i;
                }
            }

            if (windowsIdentity != null)
            {
                //find user in database by username
                var username = windowsIdentity.Name.Remove(0, 6);
                var appUser = _context.User.FirstOrDefault(m => m.Username == username);

                if (appUser != null)
                {

                    ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Id", Convert.ToString(appUser.Id)));

                    /*//add all claims from security profile
                    foreach (var p in appUser.Id)
                    {
                        ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(p.Permission, "true"));
                    }*/

                }

            }
            return await System.Threading.Tasks.Task.FromResult(context.Principal);
        }
    }
3
K7Buoy

Wissen Sie, wie man einen benutzerdefinierten System.Web.Security.MembershipProvider Implementiert? Sie sollten in der Lage sein, diese Funktion (überschreiben von ValidateUser) in Verbindung mit System.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials() zu verwenden, um sich bei Active Directory zu authentifizieren.

versuche: var pc = new PrincipalContext(ContextType.Domain, "example.com", "DC=example,DC=com"); pc.ValidateCredentials(username, password);

1
rybl