在操作之前使用 C# 传递服务器共享凭据

发布于 2024-09-27 09:56:34 字数 112 浏览 2 评论 0原文

我的应用程序使用网络上的共享目录(Windows),我想让该共享在网络上仅对给定的用户和密码可用。 在对该网络资源进行任何操作之前,有什么方法可以通过身份验证吗? *我没有使用域名。

太感谢了!

my application use a shared directory (Windows) on the network and i want to make that share available on network only to a given user and password.
Is there any way to pass authentication prior to any operations on this network resource? *I'm not using a domain.

Thank you so much!

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

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

发布评论

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

评论(1

淡忘如思 2024-10-04 09:56:34

我不完全确定如何传递 IO 操作的凭据,但通常我使用模拟类来模拟或委托特定代码块的用户凭据。

例如:

/// <summary>
/// Provides a mechanism for impersonating a user.  This is intended to be disposable, and
/// used in a using ( ) block.
/// </summary>
public class Impersonation : IDisposable
{
    #region Externals
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    private extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int
       SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr hObject);
    #endregion

    #region Fields
    private IntPtr token;
    private IntPtr tokenDuplicate;

    private WindowsIdentity identity;
    private WindowsImpersonationContext context;

    private readonly string domain;
    private readonly string username;
    private readonly string password;
    private ImpersonationLevel level;
    #endregion

    #region Constructor
    /// <summary>
    /// Initialises a new instance of <see cref="Impersonation"/>.
    /// </summary>
    /// <param name="domain">The domain of the target user.</param>
    /// <param name="username">The target user to impersonate.</param>
    /// <param name="password">The target password of the user to impersonate.</param>
    public Impersonation(string domain, string username, string password)
    {
        this.domain = domain;
        this.username = username;
        this.password = password;
        this.level = ImpersonationLevel.Impersonation;

        Logon();
    }

    /// <summary>
    /// Initialises a new instance of <see cref="Impersonation"/>.
    /// </summary>
    /// <param name="domain">The domain of the target user.</param>
    /// <param name="username">The target user to impersonate.</param>
    /// <param name="password">The target password of the user to impersonate.</param>
    /// <param name="level">The security level of this impersonation.</param>
    public Impersonation(string domain, string username, string password, ImpersonationLevel level)
    {
        this.domain = domain;
        this.username = username;
        this.password = password;
        this.level = level;

        Logon();
    }
    #endregion

    #region Methods
    /// <summary>
    /// Reverts the impersonation.
    /// </summary>
    public void Dispose()
    {
        if (context != null)
            context.Undo();

        if (token != IntPtr.Zero)
            CloseHandle(token);

        if (tokenDuplicate != IntPtr.Zero)
            CloseHandle(tokenDuplicate);
    }

    /// <summary>
    /// Performs the logon.
    /// </summary>
    private void Logon()
    {
        if (LogonUser(username, domain, password, 2, 0, out token))
        {
            if (DuplicateToken(token, (int)level, out tokenDuplicate))
            {
                identity = new WindowsIdentity(tokenDuplicate);
                context = identity.Impersonate();
            }
            else
            {
                throw new SecurityException("Unable to impersonate the user.");
            }
        }
        else
        {
            throw new SecurityException("The login details you have entered were incorrect.");
        }
    }
    #endregion
}

/// <summary>
/// Defines the possible security levels for impersonation.
/// </summary>
public enum ImpersonationLevel
{
    /// <summary>
    /// Anonymous access, the process is unable to identify the security context.
    /// </summary>
    Anonymous = 0,
    /// <summary>
    /// The process can identify the security context.
    /// </summary>
    Identification = 1,
    /// <summary>
    /// The security context can be used to access local resources.
    /// </summary>
    Impersonation = 2,
    /// <summary>
    /// The security context can be used to access remote resources.
    /// </summary>
    Delegation = 3
}

现在,它确实涉及到一点P/Invoke,但最终结果是:

class Program
{
    static void Main(string[] args)
    {
        using (var impersonation = new Impersonation("domain", "username", "password", ImpersonationLevel.Delegation))
        {
            // Do remote operations here.
        }
    }
}

对于给定的代码段,您可以模拟所需的用户来执行您的操作。如果在 using 块中使用,则在执行该代码段后,将恢复模拟并关闭句柄。

如果您不使用 using 块,则需要确保调用 Dispose 来清除所有内容。

I'm not totally sure how you would pass credentials for IO operations, but typically I use an impersonation class to impersonate or delegate user credentials for a specific block of code.

E.g.:

/// <summary>
/// Provides a mechanism for impersonating a user.  This is intended to be disposable, and
/// used in a using ( ) block.
/// </summary>
public class Impersonation : IDisposable
{
    #region Externals
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    private extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int
       SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr hObject);
    #endregion

    #region Fields
    private IntPtr token;
    private IntPtr tokenDuplicate;

    private WindowsIdentity identity;
    private WindowsImpersonationContext context;

    private readonly string domain;
    private readonly string username;
    private readonly string password;
    private ImpersonationLevel level;
    #endregion

    #region Constructor
    /// <summary>
    /// Initialises a new instance of <see cref="Impersonation"/>.
    /// </summary>
    /// <param name="domain">The domain of the target user.</param>
    /// <param name="username">The target user to impersonate.</param>
    /// <param name="password">The target password of the user to impersonate.</param>
    public Impersonation(string domain, string username, string password)
    {
        this.domain = domain;
        this.username = username;
        this.password = password;
        this.level = ImpersonationLevel.Impersonation;

        Logon();
    }

    /// <summary>
    /// Initialises a new instance of <see cref="Impersonation"/>.
    /// </summary>
    /// <param name="domain">The domain of the target user.</param>
    /// <param name="username">The target user to impersonate.</param>
    /// <param name="password">The target password of the user to impersonate.</param>
    /// <param name="level">The security level of this impersonation.</param>
    public Impersonation(string domain, string username, string password, ImpersonationLevel level)
    {
        this.domain = domain;
        this.username = username;
        this.password = password;
        this.level = level;

        Logon();
    }
    #endregion

    #region Methods
    /// <summary>
    /// Reverts the impersonation.
    /// </summary>
    public void Dispose()
    {
        if (context != null)
            context.Undo();

        if (token != IntPtr.Zero)
            CloseHandle(token);

        if (tokenDuplicate != IntPtr.Zero)
            CloseHandle(tokenDuplicate);
    }

    /// <summary>
    /// Performs the logon.
    /// </summary>
    private void Logon()
    {
        if (LogonUser(username, domain, password, 2, 0, out token))
        {
            if (DuplicateToken(token, (int)level, out tokenDuplicate))
            {
                identity = new WindowsIdentity(tokenDuplicate);
                context = identity.Impersonate();
            }
            else
            {
                throw new SecurityException("Unable to impersonate the user.");
            }
        }
        else
        {
            throw new SecurityException("The login details you have entered were incorrect.");
        }
    }
    #endregion
}

/// <summary>
/// Defines the possible security levels for impersonation.
/// </summary>
public enum ImpersonationLevel
{
    /// <summary>
    /// Anonymous access, the process is unable to identify the security context.
    /// </summary>
    Anonymous = 0,
    /// <summary>
    /// The process can identify the security context.
    /// </summary>
    Identification = 1,
    /// <summary>
    /// The security context can be used to access local resources.
    /// </summary>
    Impersonation = 2,
    /// <summary>
    /// The security context can be used to access remote resources.
    /// </summary>
    Delegation = 3
}

Now, it does involve a little P/Invoke, but the end result is:

class Program
{
    static void Main(string[] args)
    {
        using (var impersonation = new Impersonation("domain", "username", "password", ImpersonationLevel.Delegation))
        {
            // Do remote operations here.
        }
    }
}

For a given segment of code, you can impersonate the required user to perform your operations. If used in a using block, after that segment of code is executed, the impersonation is reverted and the handles closed.

If you don't use a using block, you need to ensure you call Dispose to clear everything up.

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