我有一个WPF应用程序,它将为我们公司的用户提供一种下载和上传文件到Windows服务器上的目录的方法。该应用程序将安装在每个公司成员自己的机器上。
我们希望用户无法直接访问文件浏览器中的目录,因此他们无法访问:" \ fileserver \ files"乱七八糟的。他们只能使用该应用程序上传/下载文件。
为这种情况设置权限的最佳方法是什么?我们可以在服务器上创建用户并让应用程序保存该用户的凭据吗?
答案 0 :(得分:0)
你想要考虑模仿。您可以让您的应用程序在另一个用户下执行代码。尝试在您希望应用程序执行代码的服务器上设置一个帐户。
这样做意味着您的代码仅在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服务器端服务在可访问服务器的帐户下运行。