如何将 Webcredentials 从活动用户传递到 Windows 服务?
How to pass Webcredentials from active user to Windows Service?
我需要从当前登录用户获取默认凭据并将其传递到我的 Windows 服务以检查互联网连接并将文件上传到 Dropbox。我不希望用户每次都确认 his/her 凭据。那么如何获取当前活跃用户的代理设置+用户名+密码呢?
这是我检索当前用户的代码
private static string UserName()
{
string userName = null;
ManagementScope ms = new ManagementScope();
ObjectQuery qry = new ObjectQuery("Select * from Win32_ComputerSystem");
ManagementObjectSearcher search = new ManagementObjectSearcher(ms, qry);
ManagementObjectCollection result = search.Get();
foreach (ManagementObject rec in result)
userName = rec["UserName"] as string;
string[] buffer = userName.Split('\');
return buffer[1];
}
并且此代码用于获取 Windows身份:
private static WindowsIdentity GetWindowsIdentity()
{
string userName = UserName();
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
using (UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, userName) ??
UserPrincipal.FindByIdentity(UserPrincipal.Current.Context, IdentityType.UserPrincipalName, userName))
{
return user == null
? null
: new WindowsIdentity(user.UserPrincipalName);
}
}
这是我想通过服务做的事情:
System.Diagnostics.Debugger.Launch(); //launch debugger when service runs
WindowsImpersonationContext impersonationContext;
impersonationContext = GetWindowsIdentity().Impersonate();
//try to use the currently logged in user's credentials
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
try
{
WebClient wClient = new WebClient();
string xx = wClient.DownloadString(@"https://dropbox.com");
if (xx == "") //just download the sourcecode to chek if this page is available
return false;
}
catch (Exception ex)
{
using (StreamWriter sw = new StreamWriter(@"C:\Users\Testuser\Desktop\DownloadError.txt", true))
{
sw.WriteLine(ex.ToString());
}
return false;
}
impersonationContext.Undo();
错误日志总是显示服务无法连接。当我 运行 从控制台或 WinForms 应用程序执行此操作时,它可以正常工作。
错误日志:
System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 172.217.17.238:80
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at BeeShotService.Sender.TrySend(String s) in C:\Users\Testuser\Documents\Visual Studio 2017\Projects\Project_BackupUploder\UploaderService\Sender.cs:Zeile 70.
我已经通过额外的 Class:
解决了简单 webRequests 的问题
class GetProxySettings
{
private const int INTERNET_OPTION_PROXY = 38;
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool InternetQueryOption(IntPtr hInternet, uint dwOption, IntPtr lpBuffer, ref int lpdwBufferLength);
/// <summary>
/// Access types supported by InternetOpen function.
/// </summary>
private enum InternetOpenType
{
INTERNET_OPEN_TYPE_PRECONFIG = 0,
INTERNET_OPEN_TYPE_DIRECT = 1,
INTERNET_OPEN_TYPE_PROXY = 3,
}
/// <summary>
/// Contains information that is supplied with the INTERNET_OPTION_PROXY value
/// to get or set proxy information on a handle obtained from a call to
/// the InternetOpen function.
/// </summary>
private struct INTERNET_PROXY_INFO
{
public InternetOpenType DwAccessType
{
get; set;
}
public string LpszProxy
{
get; set;
}
public string LpszProxyBypass
{
get; set;
}
}
internal string[] GetV(WindowsIdentity windowsIdentity)
{
string[] settings = new string[] { "", "" };
using (windowsIdentity.Impersonate())
{
int bufferLength = 0;
IntPtr buffer = IntPtr.Zero;
InternetQueryOption(IntPtr.Zero, INTERNET_OPTION_PROXY, IntPtr.Zero,
ref bufferLength);
try
{
buffer = Marshal.AllocHGlobal(bufferLength);
if (InternetQueryOption(IntPtr.Zero, INTERNET_OPTION_PROXY, buffer,
ref bufferLength))
{
INTERNET_PROXY_INFO proxyInfo = (INTERNET_PROXY_INFO)
// Converting structure to IntPtr.
Marshal.PtrToStructure(buffer, typeof(INTERNET_PROXY_INFO));
// Getting the proxy details.
settings[0] = proxyInfo.LpszProxy.Split(':')[0];
settings[1] = proxyInfo.LpszProxy.Split(':')[1];
}
}
catch { }
}
return settings;
}
}
您需要添加当前登录用户的 WindowsIdentity,并将 return 一个字符串[],其中 [0] = proxystring & [1] = 代理端口。
以下作为服务运行良好:
WebClient wClient = new WebClient();
wClient.Proxy = new WebProxy( GetProxySettings.GetV(GetWindowsIdentity())[0],GetProxySettings.GetV(GetWindowsIdentity())[1]);
string xx = wClient.DownloadString(@"https://www.dropbox.com");
我需要从当前登录用户获取默认凭据并将其传递到我的 Windows 服务以检查互联网连接并将文件上传到 Dropbox。我不希望用户每次都确认 his/her 凭据。那么如何获取当前活跃用户的代理设置+用户名+密码呢?
这是我检索当前用户的代码
private static string UserName()
{
string userName = null;
ManagementScope ms = new ManagementScope();
ObjectQuery qry = new ObjectQuery("Select * from Win32_ComputerSystem");
ManagementObjectSearcher search = new ManagementObjectSearcher(ms, qry);
ManagementObjectCollection result = search.Get();
foreach (ManagementObject rec in result)
userName = rec["UserName"] as string;
string[] buffer = userName.Split('\');
return buffer[1];
}
并且此代码用于获取 Windows身份:
private static WindowsIdentity GetWindowsIdentity()
{
string userName = UserName();
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
using (UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, userName) ??
UserPrincipal.FindByIdentity(UserPrincipal.Current.Context, IdentityType.UserPrincipalName, userName))
{
return user == null
? null
: new WindowsIdentity(user.UserPrincipalName);
}
}
这是我想通过服务做的事情:
System.Diagnostics.Debugger.Launch(); //launch debugger when service runs
WindowsImpersonationContext impersonationContext;
impersonationContext = GetWindowsIdentity().Impersonate();
//try to use the currently logged in user's credentials
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
try
{
WebClient wClient = new WebClient();
string xx = wClient.DownloadString(@"https://dropbox.com");
if (xx == "") //just download the sourcecode to chek if this page is available
return false;
}
catch (Exception ex)
{
using (StreamWriter sw = new StreamWriter(@"C:\Users\Testuser\Desktop\DownloadError.txt", true))
{
sw.WriteLine(ex.ToString());
}
return false;
}
impersonationContext.Undo();
错误日志总是显示服务无法连接。当我 运行 从控制台或 WinForms 应用程序执行此操作时,它可以正常工作。
错误日志:
System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 172.217.17.238:80
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at BeeShotService.Sender.TrySend(String s) in C:\Users\Testuser\Documents\Visual Studio 2017\Projects\Project_BackupUploder\UploaderService\Sender.cs:Zeile 70.
我已经通过额外的 Class:
解决了简单 webRequests 的问题class GetProxySettings
{
private const int INTERNET_OPTION_PROXY = 38;
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool InternetQueryOption(IntPtr hInternet, uint dwOption, IntPtr lpBuffer, ref int lpdwBufferLength);
/// <summary>
/// Access types supported by InternetOpen function.
/// </summary>
private enum InternetOpenType
{
INTERNET_OPEN_TYPE_PRECONFIG = 0,
INTERNET_OPEN_TYPE_DIRECT = 1,
INTERNET_OPEN_TYPE_PROXY = 3,
}
/// <summary>
/// Contains information that is supplied with the INTERNET_OPTION_PROXY value
/// to get or set proxy information on a handle obtained from a call to
/// the InternetOpen function.
/// </summary>
private struct INTERNET_PROXY_INFO
{
public InternetOpenType DwAccessType
{
get; set;
}
public string LpszProxy
{
get; set;
}
public string LpszProxyBypass
{
get; set;
}
}
internal string[] GetV(WindowsIdentity windowsIdentity)
{
string[] settings = new string[] { "", "" };
using (windowsIdentity.Impersonate())
{
int bufferLength = 0;
IntPtr buffer = IntPtr.Zero;
InternetQueryOption(IntPtr.Zero, INTERNET_OPTION_PROXY, IntPtr.Zero,
ref bufferLength);
try
{
buffer = Marshal.AllocHGlobal(bufferLength);
if (InternetQueryOption(IntPtr.Zero, INTERNET_OPTION_PROXY, buffer,
ref bufferLength))
{
INTERNET_PROXY_INFO proxyInfo = (INTERNET_PROXY_INFO)
// Converting structure to IntPtr.
Marshal.PtrToStructure(buffer, typeof(INTERNET_PROXY_INFO));
// Getting the proxy details.
settings[0] = proxyInfo.LpszProxy.Split(':')[0];
settings[1] = proxyInfo.LpszProxy.Split(':')[1];
}
}
catch { }
}
return settings;
}
}
您需要添加当前登录用户的 WindowsIdentity,并将 return 一个字符串[],其中 [0] = proxystring & [1] = 代理端口。 以下作为服务运行良好:
WebClient wClient = new WebClient();
wClient.Proxy = new WebProxy( GetProxySettings.GetV(GetWindowsIdentity())[0],GetProxySettings.GetV(GetWindowsIdentity())[1]);
string xx = wClient.DownloadString(@"https://www.dropbox.com");