2012-09-12 5 views
10

È un articolo obsoleto, ma http://msdn.microsoft.com/en-us/library/ff650308.aspx#paght000026_step3 illustra ciò che voglio fare. Ho scelto Nancy come framework per il mio web grazie alla sua semplicità e al suo approccio minimalista. Quindi, ho bisogno di un modo per autenticarsi contro Active Directory usando Nancy.Come posso autenticarmi con Active Directory in Nancy?

In ASP.NET, sembra che sia possibile passare da un provider di appartenenze basato su db ad Active Directory solo da alcune impostazioni nel proprio file web.config. Non ne ho bisogno in particolare, ma la possibilità di passare da dev a produzione sarebbe incredibile.

Come si può fare?

+1

a proposito, se questo non è disponibile in questo momento, sarò contribuendo esso .. alcuna indicazione in questo direzione sarebbe essere utile pure. –

+0

Ho appena aggiunto un problema al repository di Nancy: https://github.com/NancyFx/Nancy/issues/742 –

risposta

13

In realtà la soluzione è molto più semplice di quanto possa sembrare. Basti pensare ad Active Directory come repository per i tuoi utenti (proprio come un database). Tutto quello che devi fare è eseguire una query su AD per verificare che il nome utente e la password immessi siano validi. Quindi, basta usare Nancy's Forms Validation e gestire la connessione ad AD nella tua implementazione di IUserMapper. Ecco quello che mi è venuta per il mio mapper utente:

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

sto tenendo un record nel mio database per gestire i ruoli, per cui questa classe gestisce la verifica con AD e recupero l'utente dal database:

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 
} 

E questa classe di verificare in realtà che la combinazione username/password esiste in 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

Minor nitpick: invece di 'LoggedInUserIds.First (x => x.Key == identificatore) .Value'. , non potresti semplicemente eseguire 'LoggedInUserIds [identificatore]'? Inoltre 'LoggedInUserIds [identificatore] = adminUser.Id' nel metodo' Login'. –

+0

Potrebbe essere creato come pacchetto Nuget Nancy.ActiveDirectoryAuthentication? – pashute

+0

@pashute [Discussione AD] (https://github.com/NancyFx/Nancy/issues/742) sul tracker dei problemi di Nancy (che riporta i link a questa risposta) – Omni