我有一个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身份验证。
答案 0 :(得分:20)
可以使用表单身份验证模拟用户。以下代码可以使用。
罗伯特提到的Visual Studio Magazine article是一个很好的资源。本文中的示例代码存在一些问题,因此我在下面列出了一些工作代码。
注意:如果您使用的是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:
我不确定为什么这会被贬低,因为它有效。我添加了pinvoke签名和一些测试代码。再次,使用“以管理员身份运行”启动Visual Studio。谷歌如果你不知道如何做到这一点。
答案 1 :(得分:0)
如果您的用户使用的是IE,那么您可以打开网站的集成安全性,您的用户将以静默方式进行身份验证(无登录对话框,无登录页面)。然后你的模仿就会起作用。如果您需要定位其他浏览器,那么这可能不起作用(用户可能会看到一个登录对话框)。
您当前的模拟将永远不会起作用,因为您的用户使用其域帐户以外的帐户登录。您不能指望该网站冒充未提供其凭据的用户。这将违反基本的安全原则。
答案 2 :(得分:0)
您可能会觉得这很有用:
修改强>
在更仔细地阅读您的问题时,我不确定这种方法是否适用于您的方案;使用表单身份验证和模拟Active Directory用户登录时
答案 3 :(得分:0)
我们最近遇到了同样的问题,客户希望他们的用户可以通过AD帐户登录,然后必须使用此凭据来访问Analysis Service以及所有其他数据库。他们希望这样,因为他们实施了审计系统,所有访问必须由当前登录帐户完成。
我们尝试使用Forms身份验证和Win32 LogonUser()API来模拟部分,它可以工作,但它也要求我们将用户的密码作为纯文本。后来,我们决定使用Windows身份验证,它节省了我们很多时间(不再需要AD身份验证,手动模拟)。当然,也没有花哨的登录页面。
答案 4 :(得分:-1)
为了以防万一,有点迟了,我发现了一些对我有用的东西,它非常简单但当然只是出于测试目的......
只需使用您的用户名设置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("~/");
}
接受任何评论......
答案 5 :(得分:-6)
在Visual Studio中安装NuGet 打开您的解决方案
然后在包控制台中运行Install-Package 51Degrees.mobi
然后将51Degrees添加到您的网站。然后,您可以编辑应用程序数据中的51Degrees.mobi.config以删除重定向部分。
您现在将拥有最新的浏览器功能