简体   繁体   English

使用表单身份验证进行模拟

[英]Impersonate using Forms Authentication

I have an ASP.NET site that must use Forms Authentication and not Windows Authentication to access a ActiveDirectoryMembershipProvider . 我有一个ASP.NET站点,该站点必须使用表单身份验证而不是Windows身份验证来访问ActiveDirectoryMembershipProvider The site must use forms because they need a designed input form instead of the browser authentication popup that Windows authentication uses. 该站点必须使用表单,因为它们需要设计的输入表单,而不是Windows身份验证使用的浏览器身份验证弹出窗口。

The site needs to impersonate the user logged in via Active Directory to access user specific files. 该站点需要模拟通过Active Directory登录的用户,以访问用户特定的文件。

However, the WindowsIdentity.GetCurrent() is not the same as the HttpContext.Current.User.Identity although my web.config contains: 但是,尽管我的web.config包含以下内容,但WindowsIdentity.GetCurrent()HttpContext.Current.User.Identity是不同的:

<authentication mode="Forms">
    <forms loginUrl="login.aspx" timeout="480"/>
</authentication>
<identity impersonate="true" />

I cannot use LoginUser() and the WindowsIdentity.Impersonate() because I need to impersonate as the AD user to get their specific permissions, and I don't know the user's password because Forms takes care of logging in. 我无法使用LoginUser()WindowsIdentity.Impersonate()因为我需要模拟为AD用户来获取其特定权限,并且我不知道用户的密码,因为Forms负责登录。

Is it possible maybe from the login.aspx.cs, to take the System.Web.UI.WebControls.Login.Password , then save the LoginUser() token in a session variable for WindowsIdentity.Impersonate() later? 是否有可能从login.aspx.cs中获取System.Web.UI.WebControls.Login.Password ,然后将LoginUser()令牌保存在WindowsIdentity.Impersonate()的会话变量中? Or maybe a much more secure method of Impersonating the right way? 还是模拟正确方法的更安全的方法?

I'm confused why Forms authentication can't automatically <identity impersonate="true" /> 我很困惑为什么Forms身份验证不能自动<identity impersonate="true" />

I've read this http://msdn.microsoft.com/en-us/library/ms998351.aspx but it uses Windows Authentication. 我已经阅读了此http://msdn.microsoft.com/zh-cn/library/ms998351.aspx,但是它使用Windows身份验证。

Impersonating a user using Forms Authentication can be done. 可以使用表单身份验证模拟用户。 The following code does work . 以下代码可以正常工作

The Visual Studio Magazine article referred to by Robert is an excellent resource. Robert提到的Visual Studio Magazine文章是很好的资源。 There are a some issues with the example code in the article, so I've included some working code below. 本文中的示例代码存在一些问题,因此我在下面提供了一些工作代码。

Note: If you are using Visual Studio, make sure to launch it " Run as Administrator " to avoid problems with UAC blocking impersonation. 注意:如果您使用的是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 {
    }
}

Update: 更新:

You should also handle Application_EndRequest , because calls like Response.End() will bypass Application_PostRequestHandlerExecute . 您还应该处理Application_EndRequest ,因为像Response.End()这样的调用将绕过Application_PostRequestHandlerExecute

Another issue is that the WindowsIdentity may get garbage collected, so you should create a new WindowsIdentity and WindowsPrincipal from the logon token on every request. 另一个问题是WindowsIdentity可能会收集垃圾,因此您应在每次请求时从登录令牌中创建一个新的WindowsIdentity和WindowsPrincipal。

Update2: 更新2:

I'm not sure why this is getting downvoted, because it works. 我不知道为什么这会被否决,因为它有效。 I've added the pinvoke signature and some test code. 我添加了pinvoke签名和一些测试代码。 Again, launch Visual Studio using " Run as Administrator ". 再次,使用“ 以管理员身份运行 ”启动Visual Studio。 Google how to do that if you don't know how. Google如果不知道该怎么做。

If your users are using IE then you can turn on integrated security for the website and your users will be authenticated silently (no login dialog, no login page). 如果您的用户使用的是IE,则可以打开网站的集成安全性,并且您的用户将通过静默方式进行身份验证(没有登录对话框,没有登录页面)。 Your impersonation will then work. 这样您的模仿就可以了。 If you need to target other browsers then this may not work (the user will probably be presented with a login dialog). 如果您需要定位其他浏览器,则可能无法正常工作(可能会向用户显示一个登录对话框)。

Your current impersonation will never work because your users are logging in using an account other than their domain account. 您当前的模拟将永远无法工作,因为您的用户使用其域帐户以外的帐户登录。 You can't expect the site to impersonate a user which hasn't supplied his credentials. 您不能指望该网站会冒充没有提供其凭据的用户。 That would go against basic security principals. 这将违反基本的安全原则。

You may find this useful: 您可能会发现这很有用:

EDIT 编辑

On reading your question more closely, I am not sure if that approach would work with your scenario though; 在仔细阅读您的问题时,我不确定该方法是否适用于您的情况。 when you login using Forms Authentication and Impersonate Active Directory user 当您使用表单身份验证登录并模拟Active Directory用户时

We got the same problem recently, the customer wanted their users can log in by AD account and then this credential must be used to access Analysis Service as well as all other databases. 最近,我们遇到了同样的问题,客户希望他们的用户可以通过AD帐户登录,然后必须使用此凭据来访问Analysis Service以及所有其他数据库。 They wanted it that way because they implemented an auditing system and all access must be done by current logged in account. 他们之所以希望如此,是因为他们实施了审核系统,并且所有访问都必须由当前登录的帐户完成。

We tried Forms authentication and Win32 LogonUser() API for impersonating part, it worked but it also asks us for user's password as plain text. 我们尝试了Forms身份验证和Win32 LogonUser()API来模拟部分,它虽然有效,但它还要求我们提供纯文本形式的用户密码。 Later, we decided to utilized Windows authentication, it saves us lot of time (no more AD authentication, impersonate manually). 后来,我们决定使用Windows身份验证,它节省了很多时间(不再需要AD身份验证,而是手动模拟)。 Of course, there was also no fancy login page. 当然,也没有精美的登录页面。

For just in case, and a bit late, i found something that works for me and it's really simple but of course is only for testing purposes... 为了以防万一,并且有点晚了,我发现了一些对我有用的东西,这确实很简单,但当然仅用于测试目的...

Just set a cookie with your username. 只需使用您的用户名设置一个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("~/");
}

Any comments accepted... 接受任何评论...

In Visual Studio install NuGet Open your solution 在Visual Studio中安装NuGet打开您的解决方案

Then in the package console run Install-Package 51Degrees.mobi 然后在程序包控制台中运行Install-Package 51Degrees.mobi

It will then add 51Degrees to your website. 然后它将51Degrees添加到您的网站。 You can then edit the 51Degrees.mobi.config in your App Data to remove the redirect section. 然后,您可以在应用数据中编辑51Degrees.mobi.config,以删除重定向部分。

You will now have up to date browser capabilities 您现在将拥有最新的浏览器功能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ASP.NET MVC 模拟不使用表单身份验证 - ASP.NET MVC Impersonate not working with Forms Authentication 使用表单授权模拟用户 - Impersonate User with Forms Authorization 使用Windows身份验证时如何模拟其他Windows用户? - How to impersonate another Windows user, when using Windows authentication? 如何模拟使用aspnet_personalization Windows身份验证 - How do I impersonate using aspnet_personalization Windows Authentication ASP.Net Web窗体应用程序不通过Windows身份验证在服务器上进行身份验证 - 模拟失败 - ASP.Net Web Forms App does not authenticate on server with Windows Authentication - fails impersonate 使用表单身份验证类进行身份验证 - Using forms authentication class for authentication 使用Windows身份验证远程SQL Server时如何模拟Windows用户? - How to Impersonate Windows user when using Windows Authentication to remote SQL Server? 在同一站点上使用基本身份验证和表单身份验证 - Using Basic Authentication and Forms authentication on same site 将DocumentDB与表单身份验证和角色一起使用 - Using DocumentDB with Forms Authentication and Roles 通过WebForms在本地主机上使用表单身份验证 - Using Forms Authentication with localhost with WebForms
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM