[C#] Active Directory에 대해 사용자 이름과 비밀번호를 확인 하시겠습니까?

Active Directory에 대해 사용자 이름과 비밀번호를 확인하려면 어떻게해야합니까? 사용자 이름과 비밀번호가 올바른지 확인하고 싶습니다.



답변

.NET 3.5 이상에서 작업하는 경우 System.DirectoryServices.AccountManagement네임 스페이스를 사용하고 자격 증명을 쉽게 확인할 수 있습니다.

// create a "principal context" - e.g. your domain (could be machine, too)
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
    // validate the credentials
    bool isValid = pc.ValidateCredentials("myuser", "mypassword");
}

간단하고 신뢰할 수 있으며 최종적으로 100 % C # 관리 코드입니다. 무엇을 더 요청할 수 있습니까? 🙂

여기에 대한 모든 내용을 읽으십시오.

최신 정보:

이 다른 SO 질문 (및 그 답변)에 요약 된 것처럼 이 호출 True에는 사용자의 이전 암호가 반환 될 수있는 문제가 있습니다. 이 동작을 인식하고 이런 일이 발생해도 놀라지 마십시오 🙂 (이 점을 지적한 @MikeGledhill 덕분에!)


답변

인트라넷에서이 작업을 수행합니다

System.DirectoryServices를 사용해야합니다.

다음은 코드의 내장입니다

using (DirectoryEntry adsEntry = new DirectoryEntry(path, strAccountId, strPassword))
{
    using (DirectorySearcher adsSearcher = new DirectorySearcher(adsEntry))
    {
        //adsSearcher.Filter = "(&(objectClass=user)(objectCategory=person))";
        adsSearcher.Filter = "(sAMAccountName=" + strAccountId + ")";

        try
        {
            SearchResult adsSearchResult = adsSearcher.FindOne();
            bSucceeded = true;

            strAuthenticatedBy = "Active Directory";
            strError = "User has been authenticated by Active Directory.";
        }
        catch (Exception ex)
        {
            // Failed to authenticate. Most likely it is caused by unknown user
            // id or bad strPassword.
            strError = ex.Message;
        }
        finally
        {
            adsEntry.Close();
        }
    }
}


답변

여기에 제시된 몇 가지 솔루션에는 잘못된 사용자 / 암호와 변경해야하는 암호를 구별 할 수있는 기능이 없습니다. 다음과 같은 방법으로 수행 할 수 있습니다.

using System;
using System.DirectoryServices.Protocols;
using System.Net;

namespace ProtocolTest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                LdapConnection connection = new LdapConnection("ldap.fabrikam.com");
                NetworkCredential credential = new NetworkCredential("user", "password");
                connection.Credential = credential;
                connection.Bind();
                Console.WriteLine("logged in");
            }
            catch (LdapException lexc)
            {
                String error = lexc.ServerErrorMessage;
                Console.WriteLine(lexc);
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc);
            }
        }
    }
}

사용자 비밀번호가 잘못되었거나 사용자가 존재하지 않으면 오류에

“8009030C : LdapErr : DSID-0C0904DC, 설명 : AcceptSecurityContext 오류, 데이터 52e, v1db1”,

사용자 비밀번호를 변경해야하는 경우

“8009030C : LdapErr : DSID-0C0904DC, 설명 : AcceptSecurityContext 오류, 데이터 773, v1db1”

lexc.ServerErrorMessage데이터 값은 Win32 오류 코드 16 진수 표현입니다. 이들은 Win32 LogonUser API 호출을 호출하여 리턴되는 동일한 오류 코드입니다. 아래 목록에는 16 진수 및 10 진수 값이있는 공통 값 범위가 요약되어 있습니다.

525 user not found ​(1317)
52e invalid credentials ​(1326)
530 not permitted to logon at this time (1328)
531 not permitted to logon at this workstation (1329)
532 password expired ​(1330)
533 account disabled ​(1331) 
701 account expired ​(1793)
773 user must reset password (1907)
775 user account locked (1909)


답변

DirectoryService를 사용하는 매우 간단한 솔루션 :

using System.DirectoryServices;

//srvr = ldap server, e.g. LDAP://domain.com
//usr = user name
//pwd = user password
public bool IsAuthenticated(string srvr, string usr, string pwd)
{
    bool authenticated = false;

    try
    {
        DirectoryEntry entry = new DirectoryEntry(srvr, usr, pwd);
        object nativeObject = entry.NativeObject;
        authenticated = true;
    }
    catch (DirectoryServicesCOMException cex)
    {
        //not authenticated; reason why is in cex
    }
    catch (Exception ex)
    {
        //not authenticated due to some other exception [this is optional]
    }

    return authenticated;
}

잘못된 사용자 / 암호를 감지하려면 NativeObject 액세스가 필요합니다.


답변

불행히도 AD에서 사용자 자격 증명을 확인하는 “간단한”방법은 없습니다.

지금까지 모든 방법을 제시하면 다음과 같은 부정적 결과를 얻을 수 있습니다. 사용자의 자격 증명은 유효하지만 AD는 특정 상황에서 거짓을 반환합니다.

  • 다음 로그온시 비밀번호를 변경해야합니다.
  • 사용자 비밀번호가 만료되었습니다.

ActiveDirectory에서는 사용자가 비밀번호를 변경해야하거나 비밀번호가 만료되어 LDAP를 사용하여 비밀번호가 유효하지 않은지 확인할 수 없습니다.

암호 변경 또는 암호 만료를 확인하려면 Win32 : LogonUser ()를 호출하고 Windows 오류 코드에서 다음 두 상수를 확인하십시오.

  • ERROR_PASSWORD_MUST_CHANGE = 1907
  • ERROR_PASSWORD_EXPIRED = 1330

답변

아마도 가장 쉬운 방법은 LogInUser Win32 API를 PInvoke하는 것입니다.

http://www.pinvoke.net/default.aspx/advapi32/LogonUser.html

MSDN 참조는 여기에서 …

http://msdn.microsoft.com/en-us/library/aa378184.aspx

확실히 로그온 유형을 사용하고 싶습니다

LOGON32_LOGON_NETWORK (3)

이것은 가벼운 토큰 만 생성하며 AuthN 검사에 적합합니다. (다른 유형은 대화식 세션 등을 만드는 데 사용될 수 있습니다.)


답변

전체 .Net 솔루션은 System.DirectoryServices 네임 스페이스의 클래스를 사용하는 것입니다. AD 서버를 직접 쿼리 할 수 ​​있습니다. 이 작업을 수행하는 작은 샘플이 있습니다.

using (DirectoryEntry entry = new DirectoryEntry())
{
    entry.Username = "here goes the username you want to validate";
    entry.Password = "here goes the password";

    DirectorySearcher searcher = new DirectorySearcher(entry);

    searcher.Filter = "(objectclass=user)";

    try
    {
        searcher.FindOne();
    }
    catch (COMException ex)
    {
        if (ex.ErrorCode == -2147023570)
        {
            // Login or password is incorrect
        }
    }
}

// FindOne() didn't throw, the credentials are correct

이 코드는 직접 제공 한 자격 증명을 사용하여 AD 서버에 연결합니다. 자격 증명이 유효하지 않으면 searcher.FindOne ()에서 예외가 발생합니다. ErrorCode는 “잘못된 사용자 이름 / 암호”COM 오류에 해당하는 것입니다.

AD 사용자로 코드를 실행할 필요는 없습니다. 실제로 도메인 외부의 클라이언트에서 AD 서버의 정보를 쿼리하는 데 성공적으로 사용합니다!