IPrincipal 的文件和目录安全

发布于 2024-07-15 13:14:11 字数 263 浏览 9 评论 0原文

我需要通过 Directory.GetDirectories() 和 Directory.GetFiles() 方法访问当前 IPrincipal 有权访问的文件和目录,而不列出其他文件。 该进程本身作为网络服务运行,因此它必须在这些调用期间将主体更改为当前用户(通过 IPrincipal)。

我尝试在文件访问部分之前将 Thread.CurrentPrincipal 更改为新的 IPrincipal,但似乎没有什么区别。

我还有什么可以做的,或者我错过了什么吗?

I need to gain access to the files and directories that the current IPrincipal has access to via the Directory.GetDirectories() and Directory.GetFiles() methods, without listing the other files. The process itself is running as NETWORK SERVICE, so it must change the principal to the current user (via IPrincipal) for the duration of these calls.

I have attempted to change Thread.CurrentPrincipal to the new IPrincipal prior to the file access part, but it doesn't appear to make a difference.

Is there something else I can do, or am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情话难免假 2024-07-22 13:14:11

Windows 模拟通过使用登录详细信息获取用户令牌来解决此问题。 然后可以使用此令牌来获取 WindowsIdentity,然后使用该 WindowsIdentity 生成模拟上下文。 在此上下文范围内,您可以以模拟用户的身份访问文件系统。

当然,您需要存储用户名和密码才能使此方法发挥作用。

首先,定义从 Windows 获取用户令牌所需的 Windows API:

internal class WindowsAPI 
{
    public const int LOGON32_PROVIDER_DEFAULT = 0;
    public const int LOGON32_LOGON_INTERACTIVE = 2;

    [DllImport( "advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
    public static extern bool LogonUser( String lpszUsername, 
        String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken 
    );

    [DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
    public extern static bool CloseHandle( IntPtr handle );
}

然后,使用这些 API 获取 WindowsIdentity:

private WindowsIdentity GetIdentity( string userName, string password )
{
    _userToken = IntPtr.Zero;

    if ( !WindowsAPI.LogonUser(
        userName,
        AbbGrainDomain,
        password,
        WindowsAPI.LOGON32_LOGON_INTERACTIVE, WindowsAPI.LOGON32_PROVIDER_DEFAULT,
        ref _userToken
    ) )
    {
        int errorCode = Marshal.GetLastWin32Error();
        throw new System.ComponentModel.Win32Exception( errorCode );
    }

    return new WindowsIdentity( _userToken );
}

最后,使用此身份生成模拟上下文:

public List<string> GetDirectories( string searchPath )
{
    using ( WindowsImpersonationContext wic = GetIdentity().Impersonate() )
    {
        var directories = new List<string>();

        var di = new DirectoryInfo( searchPath );
        directories.AddRange( di.GetDirectories().Select( d => d.FullName ) );

        return directories;
    }
}

最后,使用 IDisposable 清理 Windows 句柄非常重要模式,使用存储的 _userToken:

if ( _userToken != IntPtr.Zero )
    WindowsAPI.CloseHandle( _userToken );

Windows impersonation solves this problem by using the login details to acquire a user token. This token can then be used to obtain a WindowsIdentity, which is then used to generate an impersonation context. Within this context scope, you can then access the file system as the impersonated user.

Of course, you will need to store the user name and password for this approach to work.

First, define the Windows APIs required to obtain a user token from Windows:

internal class WindowsAPI 
{
    public const int LOGON32_PROVIDER_DEFAULT = 0;
    public const int LOGON32_LOGON_INTERACTIVE = 2;

    [DllImport( "advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
    public static extern bool LogonUser( String lpszUsername, 
        String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken 
    );

    [DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
    public extern static bool CloseHandle( IntPtr handle );
}

Then, use these APIs to aquire a WindowsIdentity:

private WindowsIdentity GetIdentity( string userName, string password )
{
    _userToken = IntPtr.Zero;

    if ( !WindowsAPI.LogonUser(
        userName,
        AbbGrainDomain,
        password,
        WindowsAPI.LOGON32_LOGON_INTERACTIVE, WindowsAPI.LOGON32_PROVIDER_DEFAULT,
        ref _userToken
    ) )
    {
        int errorCode = Marshal.GetLastWin32Error();
        throw new System.ComponentModel.Win32Exception( errorCode );
    }

    return new WindowsIdentity( _userToken );
}

And finally, use this identity to generate an impersonation context:

public List<string> GetDirectories( string searchPath )
{
    using ( WindowsImpersonationContext wic = GetIdentity().Impersonate() )
    {
        var directories = new List<string>();

        var di = new DirectoryInfo( searchPath );
        directories.AddRange( di.GetDirectories().Select( d => d.FullName ) );

        return directories;
    }
}

Finally it is important to clean up the windows handle using the IDisposable pattern, using the stored _userToken:

if ( _userToken != IntPtr.Zero )
    WindowsAPI.CloseHandle( _userToken );
蹲墙角沉默 2024-07-22 13:14:11

我认为你这样做的方式不对。 您应该考虑使用模拟。 例如,请查看教程,了解如何执行此操作。

I don't think you're doing this the right way. You should look into using impersonation. For example take a look at this tutorial on how to do this.

兰花执着 2024-07-22 13:14:11

您可以使用 DllImport 和 LogonUser win32 API 来模拟另一个用户。

You can use DllImport and the LogonUser win32 API to impersonate another user.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文