我有一个 WPF 应用程序,它将为我们公司的用户提供一种将文件下载和上传到 Windows 服务器上的目录的方法。该应用程序将安装在每个公司成员自己的机器上。
我们希望这样用户不能直接在文件浏览器中访问目录,所以他们不能只是去:“\fileserver\files”然后乱七八糟。他们只能使用该应用程序上传/下载文件。
为这种情况设置权限的最佳方法是什么?我们可以在服务器上创建一个用户并让应用程序保存该用户的凭据吗?
我有一个 WPF 应用程序,它将为我们公司的用户提供一种将文件下载和上传到 Windows 服务器上的目录的方法。该应用程序将安装在每个公司成员自己的机器上。
我们希望这样用户不能直接在文件浏览器中访问目录,所以他们不能只是去:“\fileserver\files”然后乱七八糟。他们只能使用该应用程序上传/下载文件。
为这种情况设置权限的最佳方法是什么?我们可以在服务器上创建一个用户并让应用程序保存该用户的凭据吗?
您将要调查模仿。您可以让您的应用程序在另一个用户下执行代码。尝试在您希望应用程序在其下执行代码的服务器上设置一个帐户。
这样做意味着您的代码仅在 using 语句期间模拟用户,而不是在应用程序的整个生命周期中以其他用户身份运行。
此类支持跨域模拟以及同域模拟。
C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace Utils
{
public class dvImpersonator : IDisposable
{
private WindowsImpersonationContext ImpersonationContext = null;
enum LogonType
{
Interactive = 2,
Network = 3,
Batch = 4,
Service = 5,
Unlock = 7,
NetworkClearText = 8,
NewCredentials = 9
}
enum LogonProvider
{
Default = 0,
WinNT35 = 1,
WinNT40 = 2,
WinNT50 = 3
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="domainName"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool LogOn(string _UserName, string _DomainName, string _Password)
{
return ImpersonateValidUser(_UserName, _DomainName, _Password, LOGON32_LOGON_INTERACTIVE);
}
public bool CrossDomainLogOn(string _UserName, string _DomainName, string _Password)
{
return ImpersonateValidUserCrossDomain(_UserName, _DomainName, _Password);
}
public void Dispose()
{
UndoImpersonation();
}
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int LogonUserA(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);
private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
private const int LOGON32_LOGON_INTERACTIVE = 2;
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private bool ImpersonateValidUser(string _UserName, string _Domain, string _Password, int provider)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
int iRet = 0;
if (RevertToSelf())
{
//Console.WriteLine("here 1");
if ((iRet = LogonUserA(_UserName, _Domain, _Password,
provider, LOGON32_PROVIDER_DEFAULT, ref token)) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
ImpersonationContext = tempWindowsIdentity.Impersonate();
if (ImpersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
//Console.WriteLine("iret " + iRet);
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private bool ImpersonateValidUserCrossDomain(string _UserName, string _Domain, string _Password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
int iRet = 0;
if (RevertToSelf())
{
//Console.WriteLine("here 1");
if ((iRet = LogonUserA(_UserName, _Domain, _Password,
(int)LogonType.NewCredentials, (int)LogonProvider.WinNT50, ref token)) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
ImpersonationContext = tempWindowsIdentity.Impersonate();
if (ImpersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
//Console.WriteLine("iret " + iRet);
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if (ImpersonationContext != null)
{
ImpersonationContext.Undo();
}
}
}
}
样品用法:
C#
using (var LogOn = new Utils.dvImpersonator())
{
LogOn.CrossDomainLogOn(this.oConfig.User, this.oConfig.Domain, this.oConfig.Password);
//Code to Execute as other users
}
您还可以拥有一个服务器端 WCF 服务,该服务具有上传方法和下载方法。然后在您的 WPF 应用程序中使用 WCF 服务,并让您的 WCF 服务器端服务在有权访问服务器的帐户下运行。