How can I authenticate against Active Directory in Nancy?

后端 未结 1 699
温柔的废话
温柔的废话 2021-02-01 09:13

It\'s an outdated article, but http://msdn.microsoft.com/en-us/library/ff650308.aspx#paght000026_step3 illustrates what I want to do. I\'ve chosen Nancy as my web framework beca

1条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-01 09:38

    Really the solution is much simpler than it may seem. Just think of Active Directory as a repository for your users (just like a database). All you need to do is query AD to verify that the username and password entered are valid. SO, just use Nancy's Forms Validation and handle the connetion to AD in your implementation of IUserMapper. Here's what I came up with for my user mapper:

    public class ActiveDirectoryUserMapper : IUserMapper, IUserLoginManager
    {
        static readonly Dictionary LoggedInUserIds = new Dictionary(); 
    
        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;
        }
    }
    

    I'm keeping a record in my database to handle roles, so this class handles verifying with AD and fetching the user from the 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
    }
    

    And this class actually verifies that the username/password combination exist 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 讨论(0)
提交回复
热议问题