【问题标题】:File and Directory Security with IPrincipalIPrincipal 的文件和目录安全性
【发布时间】:2010-10-16 18:00:03
【问题描述】:

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

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

还有什么我可以做的,还是我错过了什么?

【问题讨论】:

  • 我想你会发现它是 IPrincipal

标签: c# security iprincipal


【解决方案1】:

Windows 模拟通过使用登录详细信息获取用户令牌来解决此问题。然后可以使用此令牌获取 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 模式清理窗口句柄很重要,使用存储的 _userToken:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      您可以使用 DllImport 和 LogonUser win32 API 来模拟其他用户。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-21
        • 1970-01-01
        • 2013-07-17
        相关资源
        最近更新 更多