我有一个 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()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,一定要启动它“以管理员身份运行”,以避免与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。

UPDATE2:

我不知道这是为什么得到downvoted,因为它的工作原理。我已经添加了PInvoke的签名和一些测试代码。再次,启动使用Visual Studio “生成作为管理员”。谷歌如何做到这一点,如果你不知道怎么办。

其他提示

如果您的用户使用IE浏览器,那么你可以打开的网站集成的安全和您的用户进行身份验证默默(没有登录对话框,没有登录页)。然后,您的模拟将工作。如果您需要针对其他浏览器,那么这可能无法正常工作(用户将有可能与一个登录对话框提交)。

由于您的用户使用比他们的域帐户以外的帐户登录您当前的模拟行不通。你不能指望该网站冒充还没有给自己的凭据的用户。这将违背基本的安全原则。

您可能会发现这很有用:

编辑

更仔细地阅读你的问题后,我不确定这种方法是否适合你的场景;当您使用表单身份验证和模拟 Active Directory 用户登录时

我们最近得到了同样的问题,客户希望其用户可以通过AD帐户登录,然后这个证书必须被用来访问分析服务以及所有其他数据库。他们希望这样的说法,因为他们实施审计系统和所有访问都必须通过当前登录帐户来完成。

我们试图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 打开你的溶液

然后,在包控制台运行安装-封装51Degrees.mobi

它将再加入51Degrees到您的网站。然后,您可以在您的应用数据编辑51Degrees.mobi.config删除重定向部分。

您现在有最新的浏览器功能

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top