简体   繁体   English

如何确保我的Windows模拟级别有效?

[英]How do I make sure that my windows impersonation level is valid?

I am dealing with a nasty issue that has me ready to tear my hair out. 我正在处理一个讨厌的问题,让我准备把头发撕掉。 I have a C# console application that uses Microsoft's HttpListener class to listen for web requests. 我有一个C#控制台应用程序,它使用Microsoft的HttpListener类来监听Web请求。 The idea is that the console application runs in the background as UserAccountA (low priv). 这个想法是控制台应用程序在后台运行UserAccountA(低priv)。 UserAccountB (Administrator, etc) comes along, accesses a webpage through the listener, and has his or her identity impersonated. UserAccountB(管理员等)出现,通过监听器访问网页,并模拟他或她的身份。 Same kind of thing IIS or WCF does. IIS或WCF也是如此。 I believe I had this working on Windows 7, but now I'm on Windows 8.1 and it's failing again. 我相信我在Windows 7上有这个工作,但现在我在Windows 8.1上,它再次失败。 Maybe I never had it to begin with, or perhaps this is a new twist. 也许我从来没有开始,或许这是一个新的转折。

If I run the program through Visual Studio, I can access it with Internet Explorer 11. For some reason, it asks me to type in my local credentials. 如果我通过Visual Studio运行程序,我可以使用Internet Explorer 11访问它。出于某种原因,它要求我输入我的本地凭据。 I'm assuming that's something to do with the out of the box behavior of IE11. 我假设这与IE11的开箱即用行为有关。 Once I type it in, it accepts it. 一旦我输入它,它接受它。 My code starts like this: 我的代码开头是这样的:

    protected virtual void Listen(object o)
    {
        HttpListener h = (HttpListener)o;

        while (h.IsListening && (this.Disposed == false))
        {
            IAsyncResult Result = null;

            Result = h.BeginGetContext(new AsyncCallback(this.ListenerCallback), h);

            Result.AsyncWaitHandle.WaitOne();
        }
    }

And is picked up like this (abbreviated): 并且像这样(缩写):

    protected virtual void ListenerCallback(IAsyncResult Result)
    {
        HttpListener h = (HttpListener)Result.AsyncState;
        HttpListenerContext context = null;
        System.Security.Principal.WindowsIdentity identity = null;

        context = h.EndGetContext(Result);

        identity = (System.Security.Principal.WindowsIdentity)context.User.Identity;

        using (System.Security.Principal.WindowsImpersonationContext wic = identity.Impersonate())
        {
             //method call to process request, under impersonation
        }
    }

I've stepped through this code when using two different accounts (one to host, one to access). 当我使用两个不同的帐户(一个用于托管,一个用于访问)时,我已经介绍了此代码。 I've verified using this statement: 我已使用此声明验证:

   system.security.principal.windowsidentity.getcurrent().name

That the current identity DOES transition. 目前的身份正在转变。 The listener is configured to start up with NTLM AuthenticationScheme. 侦听器配置为使用NTLM AuthenticationScheme启动。

I suppose the complicated part is in the method that gets invoked during impersonation. 我想复杂的部分是在模拟期间调用的方法中。 We're doing a bit of abstraction, but let me just point at the part that fails. 我们正在做一些抽象,但让我指出失败的部分。 In this case, we are connecting to SQL server using SSPI - so the entire point of the impersonation is to grab the client's existing logon and gracefully get them into SQL Server. 在这种情况下,我们使用SSPI连接到SQL服务器 - 因此模拟的全部内容是获取客户端现有的登录并优雅地将它们引入SQL Server。 Again, right now, this is all local to one computer. 同样,现在,这对于一台计算机来说都是本地的。 it is not even in an active directory domain. 它甚至不在活动目录域中。 Everything is local, with local accounts. 一切都是本地的,有本地账户。 It starts like this: 它是这样开始的:

        System.Data.Common.DbProviderFactory fact = null;

        if (UseSql())
        {
            fact = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient");
        }

No big deal. 没什么大不了。 We use the provider factory in another project constantly with no issues (but that's just a regular WPF app, nothing like this). 我们经常在另一个项目中使用提供者工厂而没有任何问题(但这只是一个普通的WPF应用程序,没有这样的)。 Right after this is where we'd set up the SQL login string with the SSPI attribute. 在此之后我们将使用SSPI属性设置SQL登录字符串。 But we don't even get that far. 但我们甚至没有那么远。 This is exactly where it fails, with this message: 这正是它失败的地方,有这条消息:

A first chance exception of type 'System.IO.FileLoadException' occurred in mscorlib.dll mscorlib.dll中发生了'System.IO.FileLoadException'类型的第一次机会异常

Additional information: Could not load file or assembly 'System.Data.OracleClient, Version=4.0.0.0, Culture=neutral, > PublicKeyToken=b77a5c561934e089' or one of its dependencies. 附加信息:无法加载文件或程序集'System.Data.OracleClient,Version = 4.0.0.0,Culture = neutral, > PublicKeyToken = b77a5c561934e089'或其依赖项之一。 Either a required impersonation level was not provided, or the provided impersonation level is invalid. 未提供所需的模拟级别,或者提供的模拟级别无效。 (Exception from HRESULT: 0x80070542) (HRESULT异常:0x80070542)

http://i854.photobucket.com/albums/ab103/srVincentVega/error7_zpsmb1xqrp0.png http://i854.photobucket.com/albums/ab103/srVincentVega/error7_zpsmb1xqrp0.png http://i854.photobucket.com/albums/ab103/srVincentVega/error7_zpsmb1xqrp0.png

We're not using Oracle at all, I'm assuming that's just the first thing it barfs on when it goes and tries to open up the DbProviderFactory. 我们根本就没有使用Oracle,我认为这只是它开始尝试打开DbProviderFactory时的第一件事。 To me, the key is that impersonation level thing. 对我而言,关键在于冒充级别的事情。 In this particular experiment, both accounts (A & B) are local administrators. 在此特定实验中,两个帐户(A和B)都是本地管理员。 I've ensured via local Security Policy that they can impersonate accounts after login. 我已通过本地安全策略确保他们可以在登录后模拟帐户。 And if I look at my event log, the impersonation DOES seem to be working... 如果我查看我的事件日志,模仿似乎正在起作用......

Special privileges assigned to new logon. 分配给新登录的特权。

Subject: Security ID: 主题:安全ID:

pc1\\userA PC1 \\用户A

Account Name: userA 帐户名称:userA

Account Domain: pc1 Logon ID: 0xC4D0F3F 帐户域:pc1登录ID:0xC4D0F3F

Privileges: 特权:

SeSecurityPrivilege SeSecurityPrivilege权限

SeTakeOwnershipPrivilege SeTakeOwnershipPrivilege

SeLoadDriverPrivilege SeLoadDriverPrivilege

SeBackupPrivilege SeBackupPrivilege

SeRestorePrivilege SeRestorePrivilege

SeDebugPrivilege SeDebugPrivilege

SeSystemEnvironmentPrivilege SeSystemEnvironmentPrivilege

SeImpersonatePrivilege SeImpersonatePrivilege

I've tried so many variations here that I'm starting to hinder my own analysis. 我在这里尝试了很多变化,我开始阻碍我自己的分析。 I'm basically back to square one and don't know how to approach this. 我基本上回到原点,不知道如何处理这个问题。 Does anyone have any advice or tips? 有没有人有任何建议或提示? This seems like it should be a very simple thing to do. 这似乎应该是一件非常简单的事情。 I am not sure why I am having so much trouble. 我不知道为什么我遇到这么多麻烦。 Maybe I just need to toss out the use of the DbProviderFactory and go with OleDb or whatever. 也许我只需要抛弃使用DbProviderFactory并使用OleDb或其他任何东西。 But I have not confirmed that I can load ANY libraries at run time after impersonation. 但我还没有确认我可以在模仿后在运行时加载任何库。 Maybe that's something to do. 也许这是可以做的事情。 However, I would be very grateful for any help. 但是,我会非常感谢任何帮助。

Thanks, 谢谢,

John 约翰

One last thing, here are reproduction steps: 最后一件事,这是复制步骤:

Create a secondary user on your computer. 在您的计算机上创建辅助用户。 Log in to create the profile. 登录以创建配置文件。 Log out and log back in as usual. 注销并像往常一样重新登录。 Run Visual Studio as that secondary user (there are a few ways to do this, shift + right click on the VS icon), and within, make a C# console application with this skeleton: 以该次要用户身份运行Visual Studio(有几种方法可以执行此操作,右键单击VS图标),然后使用此框架创建一个C#控制台应用程序:

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (HttpListener h = new HttpListener())
                {
                    h.Prefixes.Add("http://+:8090/");

                    h.AuthenticationSchemes = AuthenticationSchemes.Ntlm;

                    h.Start();

                    Console.WriteLine("Running");

                    HttpListenerContext context = h.GetContext();

                    System.Security.Principal.WindowsIdentity identity = null;
                    identity = (System.Security.Principal.WindowsIdentity)context.User.Identity;

                    using (System.Security.Principal.WindowsImpersonationContext wic = identity.Impersonate())
                    {
                        System.Data.Common.DbProviderFactory fact = null;
                        fact = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient");
                    }

                    Console.ReadLine();

                    h.Stop();
                }
            }
        }
    }

Debug/Run the console app. 调试/运行控制台应用程序。 Just call up Internet Explorer (vanilla, using your primary account) and access that URL ( http://machinename:8090 ). 只需调用Internet Explorer(vanilla,使用您的主帐户)并访问该URL( http:// machinename:8090 )。 The exception occurs 发生异常

在此输入图像描述 http://i854.photobucket.com/albums/ab103/srVincentVega/error8_zpsilkay0bl.png http://i854.photobucket.com/albums/ab103/srVincentVega/error8_zpsilkay0bl.png

Well, I read like half-way through and stopped at the exception you are getting: 好吧,我读到中途,并在你获得的例外情况下停下来:

A first chance exception of type 'System.IO.FileLoadException' occurred in mscorlib.dll 

The problem here is that the account that you are using to run the service has limited access to load .Net framework core libraries before it can even perform impersonation. 这里的问题是,用于运行服务的帐户在甚至可以执行模拟之前,对加载.Net框架核心库的访问权限有限。 Usually such an account which is used to host a service has admin privileges on the node where the service is hosted. 通常,用于托管服务的此类帐户在托管服务的节点上具有管理员权限。

Also to allow impersonation you need to give the service account the privileges to do so using the local security policies - Local Policies - User Rights Assignment: 此外,为了允许模拟,您需要使用本地安全策略为本地服务帐户授予权限 - 本地策略 - 用户权限分配:

Act as part of the operating system 作为操作系统的一部分

This user right allows a process to impersonate any user without authentication. 此用户权限允许进程在没有身份验证的情况下模拟任何用户。 The process can therefore gain access to the same local resources as that user. 因此,该过程可以访问与该用户相同的本地资源。

Impersonate a client after authentication 身份验证后模拟客户端

Assigning this privilege to a user allows programs running on behalf of that user to impersonate a client. 将此权限分配给用户允许代表该用户运行的程序模拟客户端。

Also note if you use kerberos instead of NTLM you would need to setup SPN's as well as delegation targets in AD (Actice Directory). 另请注意,如果您使用kerberos而不是NTLM,则需要在AD(Actice目录)中设置SPN和委派目标。

I don't know if this will assist you but these are things we ran into doing impersonation/delegation. 我不知道这是否会对你有所帮助,但这些都是我们冒充假冒/委托的事情。

Oh yeah, impersonation level must be set to delegation if you perform more than one hop to perform impersonation. 哦,是的,如果您执行多次跳转来执行模拟,则必须将模拟级别设置为委派。

暂无
暂无

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

相关问题 如何使用RegEx确保在TextBox&gt;中写入了有效的电子邮件? - How can I use RegEx to make sure a valid email is written in my TextBox>? 如何解决“请确保文件可访问并且它是有效的程序集或 COM 组件”? - How do I resolve “Please make sure that the file is accessible and that it is a valid assembly or COM component”? 如何确定VS TFS的签入中包含csproj文件? - How do I make sure a my csproj file is included in my check-in within VS TFS? 如何确保程序在Windows Server 2012上的所有会话中仅运行一次? - How do I make sure a program is only running once across all sessions on a windows server 2012? 如何确保无需计时器即可在Android应用程序中使用Azure移动服务? - How do I make sure I can use Azure Mobile Services in my Android app without a Timer? 如何确保我的外部进程创建一个新文件而不是覆盖它? - How do I make sure my external process creates a new file instead of overwriting it? 如何确保下载的内容和列表具有匹配的索引? - How do I make sure downloaded content and my list have matching indexes? 如何明确确保我的还原,构建和发布设置在.Net Core中是否一致? - How do I explicitly make sure my restore, build and publish settings are consistent in .Net Core? 我如何确保我在WPF上收集的签名在法庭上合法 - How do i make sure my collected signature on wpf is legal in court 我如何确保列表 <T> .Contains(T)适用于我的自定义类? - How do i make sure that List<T>.Contains(T) works with my custom class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM