使用表單身份驗證進行模擬
我有一個 ASP.NET 站點,它必須使用表單身份驗證而不是 Windows 身份驗證來訪問
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()and ,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 身份驗證。
可以使用表單身份驗證模擬使用者。下面的程式碼確實有效。
Robert 提到的Visual Studio Magazine 文章是一個極好的資源。文章中的範常式式碼存在一些問題,因此我在下麵包含了一些工作程式碼。
注意:如果您使用的是 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,因為呼叫likeResponse.End()會繞過Application_PostRequestHandlerExecute。另一個問題是 WindowsIdentity 可能會被垃圾收集,因此您應該在每次請求時從登錄令牌創建一個新的 WindowsIdentity 和 WindowsPrincipal。
更新2:
我不確定為什麼這會被否決,因為它有效。我添加了 pinvoke 簽名和一些測試程式碼。再次,使用“以管理員身份執行”啟動 Visual Studio 。如果你不知道怎麼做,Google如何做到這一點。