Rob*_*ert 25 asp.net impersonation forms-authentication active-directory windows-authentication
我有一个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" />
Run Code Online (Sandbox Code Playgroud)
我无法使用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身份验证.
use*_*806 20
可以使用表单身份验证模拟用户.以下代码确实有效.
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 {
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
你也应该处理Application_EndRequest,因为呼叫Response.End()会绕过Application_PostRequestHandlerExecute.
另一个问题是WindowsIdentity可能会收集垃圾,因此您应该在每次请求时从登录令牌创建新的WindowsIdentity和WindowsPrincipal.
UPDATE2:
我不确定为什么这会被贬低,因为它有效.我添加了pinvoke签名和一些测试代码.再次,使用" 以管理员身份运行 "启动Visual Studio .谷歌如果你不知道如何做到这一点.
| 归档时间: |
|
| 查看次数: |
22298 次 |
| 最近记录: |