Аутентификация Active Directory в ASP.NET Core 2.0 LDAP

В прошлом я нашел много информации о том, что аутентификация LDAP еще не включена, но вы можете обойти это, используя сторонние пакеты. Однако, похоже, что аутентификация LDAP была реализована еще в январе. Я не могу найти информацию о том, КАК это реализовать.

У меня уже есть пользовательская аутентификация в моем проекте, мне просто нужна логика для заполнения метода HandleAuthenticateAsync.

Я пытался использовать другие примеры, но они не работают с .NET Core 2.0.

Вот единственный соответствующий мне код, который я могу опубликовать

protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
    // Get Authorization header value
    if (!Request.Headers.TryGetValue(HeaderNames.Authorization, out var authorization)) {
        return Task.FromResult(AuthenticateResult.Fail("Cannot read authorization header."));
    }

    // TODO: Authenticate user

    // Create authenticated user ticket
    var identities = new List<ClaimsIdentity> { new ClaimsIdentity("custom auth type") };
    var ticket = new AuthenticationTicket(new ClaimsPrincipal(identities), Options.Scheme);

    return Task.FromResult(AuthenticateResult.Success(ticket));

    // else User not authenticated
    return Task.FromResult(AuthenticateResult.Fail("Invalid auth key."));
}

Итак, мой вопрос: как мне реализовать аутентификацию LDAP в .NET Core 2.0?

Ответ 1

Спасибо Win Answer за указание на то, что мне нужно использовать Windows Compatibility Pack, я смог понять это.

Сначала мне нужно было установить пакет Nuget.

Install-Package Microsoft.Windows.Compatibility 

В то время мне требовалась предварительная версия, поэтому я добавил -Version 2.0.0-preview1-26216-02 в конце этой команды

Затем добавьте операторы использования для System.DirectoryServices и System.DirectoryServices.AccountManagement

Затем просто подключите эту логику к моему методу HandleAuthenticateAsync:

const string LDAP_PATH = "EX://exldap.example.com:5555";
const string LDAP_DOMAIN = "exldap.example.com:5555";

using (var context = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN, "service_acct_user", "service_acct_pswd")) {
    if (context.ValidateCredentials(username, password)) {
        using (var de = new DirectoryEntry(LDAP_PATH))
        using (var ds = new DirectorySearcher(de)) {
            // other logic to verify user has correct permissions

            // User authenticated and authorized
            var identities = new List<ClaimsIdentity> { new ClaimsIdentity("custom auth type") };
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identities), Options.Scheme);
            return Task.FromResult(AuthenticateResult.Success(ticket));
        }
    }
}

// User not authenticated
return Task.FromResult(AuthenticateResult.Fail("Invalid auth key."));

Ответ 2

Согласно # 2089, он доступен только в пакете совместимости Windows для .NET Core. В настоящее время я использую Novell.Directory.Ldap.NETStandard.

public bool ValidateUser(string domainName, string username, string password)
{
   string userDn = $"{username}@{domainName}";
   try
   {
      using (var connection = new LdapConnection {SecureSocketLayer = false})
      {
         connection.Connect(domainName, LdapConnection.DEFAULT_PORT);
         connection.Bind(userDn, password);
         if (connection.Bound)
            return true;
      }
   }
   catch (LdapException ex)
   {
      // Log exception
   }
   return false;
}

Для проверки подлинности и авторизации мы можем использовать промежуточное программное обеспечение проверки подлинности cookie с претензиями.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
   ILoggerFactory loggerFactory)
{
   app.UseCookieAuthentication(new CookieAuthenticationOptions
   {                
      AuthenticationScheme = "AuthenticationScheme",
      LoginPath = new PathString("/Account/Login"),
      AccessDeniedPath = new PathString("/Common/AccessDenied"),
      AutomaticAuthenticate = true,
      AutomaticChallenge = true
   });
}

У него мало движущихся частей, поэтому я создал рабочий пример проекта на GitHub. Есть две основные части - LdapAuthenticationService и SignInManager.

Ответ 3

Аутентификация LDAP может быть достигнута с использованием пространства имен System.DirectoryServices.Protocols.

public Boolean IsAuthenticated(string username, string password,string domain)
{
    Boolean authenticated = false;
    //pass the connectionString here
    using (LdapConnection connection = new LdapConnection(connectionString))
    {
       try
       {
           username = username + domain;
           connection.AuthType = AuthType.Basic;
           connection.SessionOptions.ProtocolVersion = 3;
           var credential = new NetworkCredential(username, password);
           connection.Bind(credential);
           authenticated = true;
           return authenticated;
       }
       catch (LdapException)
       {
           return authenticated;
       }
       finally
       {
           connection.Dispose();
       }
   }}