2012-09-12 22 views
10

Es un artículo obsoleto, pero http://msdn.microsoft.com/en-us/library/ff650308.aspx#paght000026_step3 ilustra lo que quiero hacer. Elegí Nancy como mi marco web debido a su simplicidad y enfoque poco ceremonial. Entonces, necesito una forma de autenticarme contra Active Directory usando Nancy.¿Cómo puedo autenticarme contra Active Directory en Nancy?

En ASP.NET, parece que puede simplemente cambiar entre un proveedor de membresía basado en db y Active Directory solo con algunas configuraciones en su archivo web.config. No lo necesito específicamente, pero la capacidad de cambiar entre dev y producción sería increíble.

¿Cómo se puede hacer esto?

+1

Por cierto, si esto no está disponible en este momento, estará contribuyendo ella .. ningún tipo de orientación en ese dirección sería ser útil también –

+0

Acabo de agregar un problema al repositorio de Nancy: https://github.com/NancyFx/Nancy/issues/742 –

Respuesta

13

Realmente la solución es mucho más simple de lo que parece. Solo piense en Active Directory como un repositorio para sus usuarios (como una base de datos). Todo lo que necesita hacer es consultar AD para verificar que el nombre de usuario y la contraseña ingresados ​​sean válidos. ASÍ, use la Validación de Formularios de Nancy y maneje la conexión a AD en su implementación de IUserMapper. Esto es lo que ocurrió con mi usuario asignador:

public class ActiveDirectoryUserMapper : IUserMapper, IUserLoginManager 
{ 
    static readonly Dictionary<Guid, long> LoggedInUserIds = new Dictionary<Guid, long>(); 

    readonly IAdminUserValidator _adminUserValidator; 
    readonly IAdminUserFetcher _adminUserFetcher; 
    readonly ISessionContainer _sessionContainer; 

    public ActiveDirectoryUserMapper(IAdminUserValidator adminUserValidator, IAdminUserFetcher adminUserFetcher, ISessionContainer sessionContainer) 
    { 
     _adminUserValidator = adminUserValidator; 
     _adminUserFetcher = adminUserFetcher; 
     _sessionContainer = sessionContainer; 
    } 

    public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context) 
    { 
     _sessionContainer.OpenSession(); 
     var adminUserId = LoggedInUserIds.First(x => x.Key == identifier).Value; 
     var adminUser = _adminUserFetcher.GetAdminUser(adminUserId); 
     return new ApiUserIdentity(adminUser); 
    } 

    public Guid Login(string username, string clearTextPassword, string domain) 
    { 
     var adminUser = _adminUserValidator.ValidateAndReturnAdminUser(username, clearTextPassword, domain); 
     var identifier = Guid.NewGuid(); 
     LoggedInUserIds.Add(identifier, adminUser.Id); 
     return identifier; 
    } 
} 

estoy manteniendo un registro en mi base de datos para manejar las funciones, por lo que esta clase se encarga de verificar con EA y ir a buscar al usuario de la base de datos:

public class AdminUserValidator : IAdminUserValidator 
{ 
    readonly IActiveDirectoryUserValidator _activeDirectoryUserValidator; 
    readonly IAdminUserFetcher _adminUserFetcher; 

    public AdminUserValidator(IAdminUserFetcher adminUserFetcher, 
           IActiveDirectoryUserValidator activeDirectoryUserValidator) 
    { 
     _adminUserFetcher = adminUserFetcher; 
     _activeDirectoryUserValidator = activeDirectoryUserValidator; 
    } 

    #region IAdminUserValidator Members 

    public AdminUser ValidateAndReturnAdminUser(string username, string clearTextPassword, string domain) 
    { 
     _activeDirectoryUserValidator.Validate(username, clearTextPassword, domain); 

     return _adminUserFetcher.GetAdminUser(1);    
    } 

    #endregion 
} 

Y esta clase realidad verifica que la combinación de nombre de usuario/contraseña existe en Active Directory:

public class ActiveDirectoryUserValidator : IActiveDirectoryUserValidator 
{ 
    public void Validate(string username, string clearTextPassword, string domain) 
    { 
     using (var principalContext = new PrincipalContext(ContextType.Domain, domain)) 
     { 
      // validate the credentials 
      bool isValid = principalContext.ValidateCredentials(username, clearTextPassword); 
      if (!isValid) 
       throw new Exception("Invalid username or password."); 
     } 

    } 
} 
+0

Minit nitpick: en lugar de 'LoggedInUserIds.First (x => x.Key == identifier) ​​.Value' , ¿no podrías hacer 'LoggedInUserIds [identifier]'? También 'LoggedInUserIds [identifier] = adminUser.Id' en el método' Login'. –

+0

¿Podría hacerse esto como un paquete Nuget Nancy.ActiveDirectoryAuthentication? – pashute

+0

@pashute [Discusión AD] (https://github.com/NancyFx/Nancy/issues/742) en el rastreador de problemas de Nancy (que contiene enlaces a esta respuesta) – Omni

Cuestiones relacionadas