문제

Windows 인증이 아닌 양식 인증을 사용하여 액세스해야 하는 ASP.NET 사이트가 있습니다. ActiveDirectoryMembershipProvider.사이트에서는 Windows 인증에서 사용하는 브라우저 인증 팝업 대신 설계된 입력 양식이 필요하므로 양식을 사용해야 합니다.

사이트는 사용자 특정 파일에 액세스하기 위해 Active Directory를 통해 로그인한 사용자를 가장해야 합니다.

그러나, 그 WindowsIdentity.GetCurrent() 와 동일하지 않습니다 HttpContext.Current.User.Identity 내 web.config에는 다음이 포함되어 있습니다.

<authentication mode="Forms">
    <forms loginUrl="login.aspx" timeout="480"/>
</authentication>
<identity impersonate="true" />

사용할 수 없습니다 LoginUser() 그리고 WindowsIdentity.Impersonate() 특정 권한을 얻으려면 AD 사용자로 가장해야 하고 Forms가 로그인을 관리하기 때문에 사용자의 비밀번호를 모르기 때문입니다.

아마도 login.aspx.cs에서 System.Web.UI.WebControls.Login.Password, 그런 다음 LoginUser() 세션 변수의 토큰 WindowsIdentity.Impersonate() 나중에?아니면 올바른 방식으로 가장하는 훨씬 더 안전한 방법일까요?

양식 인증이 자동으로 수행되지 않는 이유가 무엇인지 궁금합니다. <identity impersonate="true" />

나는 이것을 읽었다 http://msdn.microsoft.com/en-us/library/ms998351.aspx 하지만 Windows 인증을 사용합니다.

도움이 되었습니까?

해결책

양식 인증을 사용하여 사용자를 가장할 수 있습니다.다음 코드 작동합니까.

그만큼 Visual Studio 매거진 기사 Robert가 언급한 훌륭한 자료입니다.기사의 예제 코드에는 몇 가지 문제가 있으므로 아래에 몇 가지 작동 코드를 포함했습니다.

메모:Visual Studio를 사용하는 경우 반드시 실행하세요."관리자로 실행" UAC 차단 가장 문제를 방지합니다.

// in your login page (hook up to OnAuthenticate event)
protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e)
{
    int token;
    // replace "YOURDOMAIN" with your actual domain name
    e.Authenticated = LogonUser(LoginUser.UserName,"YOURDOMAIN",LoginUser.Password,8,0,out token);
    if (e.Authenticated) {
        Session.Add("principal", new WindowsPrincipal(new WindowsIdentity(new IntPtr(token))));
    }
}

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,
    int dwLogonType, int dwLogonProvider, out int TokenHandle);


// in global.asax.cs
void Application_PreRequestHandlerExecute(object send, EventArgs e)
{
    if (Thread.CurrentPrincipal.Identity.IsAuthenticated == true && HttpContext.Current.Session != null) {
        WindowsPrincipal windowsPrincipal = (WindowsPrincipal)Session["principal"];
        Session["principal"] = (GenericPrincipal)Thread.CurrentPrincipal;
        Thread.CurrentPrincipal = windowsPrincipal;
        HttpContext.Current.User = windowsPrincipal;
        HttpContext.Current.Items["identity"] = ((WindowsIdentity)windowsPrincipal.Identity).Impersonate();
    }
}

// in global.asax.cs
void Application_PostRequestHandlerExecute(object send, EventArgs e)
{
    if (HttpContext.Current.Session != null && Session["principal"] as GenericPrincipal != null) {
        GenericPrincipal genericPrincipal = (GenericPrincipal)Session["principal"];
        Session["principal"] = (WindowsPrincipal)Thread.CurrentPrincipal;
        Thread.CurrentPrincipal = genericPrincipal;
        HttpContext.Current.User = genericPrincipal;
        ((WindowsImpersonationContext)HttpContext.Current.Items["identity"]).Undo();
    }
}

// test that impersonation is working (add this and an Asp:Label to a test page)
protected void Page_Load(object sender, EventArgs e)
{
    try {
        // replace YOURSERVER and YOURDB with your actual server and database names
        string connstring = "data source=YOURSERVER;initial catalog=YOURDB;integrated security=True";
        using (SqlConnection conn = new SqlConnection(connstring)) {
            conn.Open();
            SqlCommand cmd = new SqlCommand("SELECT SUSER_NAME()", conn);
            using (SqlDataReader rdr = cmd.ExecuteReader()) {
                rdr.Read();
                Label1.Text = "SUSER_NAME() = " + rdr.GetString(0);
            }
        }
    }
    catch {
    }
}

업데이트:

당신도 처리해야합니다 Application_EndRequest, 다음과 같은 호출 때문에 Response.End() 우회할 것이다 Application_PostRequestHandlerExecute.

또 다른 문제는 WindowsIdentity가 가비지 수집될 수 있으므로 모든 요청의 로그온 토큰에서 새 WindowsIdentity 및 WindowsPrincipal을 만들어야 한다는 것입니다.

업데이트2:

이것이 작동하기 때문에 왜 반대표를 받는지 잘 모르겠습니다.pinvoke 서명과 일부 테스트 코드를 추가했습니다.다시 "를 사용하여 Visual Studio를 시작합니다.관리자로 실행".방법을 모르는 경우 Google에서 방법을 알아보세요.

다른 팁

사용자가 IE를 사용하는 경우 웹 사이트의 통합 보안을 켜면 사용자가 조용히 인증됩니다 (로그인 대화 상자, 로그인 페이지 없음). 그러면 가장가 효과가있을 것입니다. 다른 브라우저를 타겟팅 해야하는 경우 작동하지 않을 수 있습니다 (사용자에게 로그인 대화 상자가 표시 될 수 있음).

사용자가 도메인 계정 이외의 계정을 사용하여 로그인하기 때문에 현재 가장 한 사람은 작동하지 않습니다. 사이트가 자신의 자격 증명을 제공하지 않은 사용자를 가장 할 것으로 기대할 수 없습니다. 그것은 기본 보안 원칙에 위배 될 것입니다.

이 유용한 것을 알 수 있습니다.

편집하다

귀하의 질문을 더 자세히 읽을 때, 나는 그 접근법이 당신의 시나리오와 함께 작동하는지 확실하지 않습니다. Forms 인증을 사용하여 로그인하고 Active Directory 사용자를 가장합니다.

최근에 동일한 문제가 발생했으며 고객은 사용자가 AD 계정으로 사용자가 로그인 할 수 있기를 원했고이 자격 증명은 다른 모든 데이터베이스뿐만 아니라 분석 서비스에 액세스하는 데 사용해야합니다. 그들은 감사 시스템을 구현했기 때문에 그런 식으로 원했고 모든 액세스는 현재 로그인 된 계정으로 수행해야합니다.

우리는 Forms Authentication 및 Win32 Logonuser () API를 가장 한 부분을 가장했지만 효과가 있었지만 사용자의 비밀번호를 일반 텍스트로 요구합니다. 나중에, 우리는 Windows 인증을 활용하기로 결정했습니다. 많은 시간을 절약 할 수 있습니다 (더 이상 광고 인증이없고 수동으로 가장합니다). 물론 멋진 로그인 페이지도 없었습니다.

만일과 조금 늦었을 때, 나는 나에게 적합한 것을 발견했고 정말 간단하지만 물론 테스트 목적으로 만 ...

사용자 이름으로 쿠키를 설정하십시오.

//Login button. You can give whatever input to the form
protected void Login_Click(object sender, EventArgs e)
{
    FormsAuthentication.SetAuthCookie("your_username", createPersistentCookie: true);
    Response.Redirect("~/");
}

수락 된 모든 의견 ...

Visual Studio에서 Nuget 설치 솔루션을 엽니 다

그런 다음 패키지 콘솔에서 설치 패키지 51degrees.mobi에서 실행됩니다

그런 다음 웹 사이트에 51도를 추가합니다. 그런 다음 앱 데이터에서 51degrees.mobi.config를 편집하여 리디렉션 섹션을 제거 할 수 있습니다.

이제 최신 브라우저 기능이 있습니다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top