asp.net – 使用表单验证模拟

我有一个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()的会话变量中?或者也许是一个更安全的假冒正确方法方法

我很困惑为什么Forms身份验证不能自动< identity impersonate =“true”/>

我已经阅读了这个http://msdn.microsoft.com/en-us/library/ms998351.aspx,但它使用Windows身份验证。

解决方法

可以使用Forms Authentication来模拟用户。以下代码可以正常工作。

罗伯特提到的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,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。谷歌怎么做,如果你不知道如何。

相关文章

### 创建一个gRPC服务项目(grpc服务端)和一个 webapi项目(...
一、SiganlR 使用的协议类型 1.websocket即时通讯协议 2.Ser...
.Net 6 WebApi 项目 在Linux系统上 打包成Docker镜像,发布为...
一、 PD简介PowerDesigner 是一个集所有现代建模技术于一身的...
一、存储过程 存储过程就像数据库中运行的方法(函数) 优点:...
一、Ueditor的下载 1、百度编辑器下载地址:http://ueditor....