簡體   English   中英

使用表單身份驗證進行模擬

[英]Impersonate using Forms Authentication

我有一個ASP.NET站點,該站點必須使用表單身份驗證而不是Windows身份驗證來訪問ActiveDirectoryMembershipProvider 該站點必須使用表單,因為它們需要設計的輸入表單,而不是Windows身份驗證使用的瀏覽器身份驗證彈出窗口。

該站點需要模擬通過Active Directory登錄的用戶,以訪問用戶特定的文件。

但是,盡管我的web.config包含以下內容,但WindowsIdentity.GetCurrent()HttpContext.Current.User.Identity是不同的:

<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()的會話變量中? 還是模擬正確方法的更安全的方法?

我很困惑為什么Forms身份驗證不能自動<identity impersonate="true" />

我已經閱讀了此http://msdn.microsoft.com/zh-cn/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 ,因為像Response.End()這樣的調用將繞過Application_PostRequestHandlerExecute

另一個問題是WindowsIdentity可能會收集垃圾,因此您應在每次請求時從登錄令牌中創建一個新的WindowsIdentity和WindowsPrincipal。

更新2:

我不知道為什么這會被否決,因為它有效。 我添加了pinvoke簽名和一些測試代碼。 再次,使用“ 以管理員身份運行 ”啟動Visual Studio。 Google如果不知道該怎么做。

如果您的用戶使用的是IE,則可以打開網站的集成安全性,並且您的用戶將通過靜默方式進行身份驗證(沒有登錄對話框,沒有登錄頁面)。 這樣您的模仿就可以了。 如果您需要定位其他瀏覽器,則可能無法正常工作(可能會向用戶顯示一個登錄對話框)。

您當前的模擬將永遠無法工作,因為您的用戶使用其域帳戶以外的帳戶登錄。 您不能指望該網站會冒充沒有提供其憑據的用戶。 這將違反基本的安全原則。

您可能會發現這很有用:

編輯

在仔細閱讀您的問題時,我不確定該方法是否適用於您的情況。 當您使用表單身份驗證登錄並模擬Active Directory用戶時

最近,我們遇到了同樣的問題,客戶希望他們的用戶可以通過AD帳戶登錄,然后必須使用此憑據來訪問Analysis Service以及所有其他數據庫。 他們之所以希望如此,是因為他們實施了審核系統,並且所有訪問都必須由當前登錄的帳戶完成。

我們嘗試了Forms身份驗證和Win32 LogonUser()API來模擬部分,它雖然有效,但它還要求我們提供純文本形式的用戶密碼。 后來,我們決定使用Windows身份驗證,它節省了很多時間(不再需要AD身份驗證,而是手動模擬)。 當然,也沒有精美的登錄頁面。

為了以防萬一,並且有點晚了,我發現了一些對我有用的東西,這確實很簡單,但當然僅用於測試目的...

只需使用您的用戶名設置一個cookie。

//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打開您的解決方案

然后在程序包控制台中運行Install-Package 51Degrees.mobi

然后它將51Degrees添加到您的網站。 然后,您可以在應用數據中編輯51Degrees.mobi.config,以刪除重定向部分。

您現在將擁有最新的瀏覽器功能

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM