在我的网站(用 ASP.NET/C# 编写)上,我希望管理员能够启动某个服务。我为此的代码是:
ServiceController svcController = new ServiceController("InvidualFileConversion");
if (svcController != null)
{
try
{
svcController.Stop();
svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
svcController.Start();
}
catch (Exception ex)
{
// error
}
}
现在,当我运行此命令时,我收到错误“无法在计算机上打开 InvidualFileConversion 服务”,并附加消息:“访问被拒绝”。
我知道这是权限问题,但是我如何给自己适当的权限?不要在我应该写的地方给出答案: ,因为我已经尝试过但它不起作用。另外,我认为当我只需要这几行代码时,这并不是为整个网站设置此功能的最佳方法。
EDIT:我已将其添加到我的代码中,但它仍然不起作用,我在同一位置遇到相同的异常。现在看起来像这样:
protected void ConvertLink_OnClick(object sender, EventArgs e)
{
//convert();
try
{
//--need to impersonate with the user having appropriate rights to start the service
Impersonate objImpersonate = new Impersonate(domainName, userName, userPassword);
if (objImpersonate.impersonateValidUser())
{
//--write code to start/stop the window service
startWindowsService();
objImpersonate.undoImpersonation();
}
}
catch (Exception Ex)
{ Response.Write(Ex.Message + Ex.InnerException.Message); }
}
private void startWindowsService()
{
ServiceController svcController = new ServiceController("InvidualFileConversion");
if (svcController != null)
{
try
{
svcController.Stop();
svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
svcController.Start();
}
catch (Exception ex)
{
// error
}
}
}
我有一个模拟类,如下所示:
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Security.Principal;
using System.Runtime.InteropServices;
/// <summary>
/// Summary description for Impersonate
/// </summary>
public class Impersonate
{
#region "Class Members"
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
#endregion
#region "Class Properties"
public string domainName { get; set; }
public string userName { get; set; }
public string userPassword { get; set; }
#endregion
public Impersonate()
{
//
// TODO: Add constructor logic here
//
}
public Impersonate(string domainName, string userName, string userPassword)
{
this.domainName = domainName;
this.userName = userName;
this.userPassword = userPassword;
}
#region "Impersonation Code"
[DllImport("advapi32.dll")]
public 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)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public bool impersonateValidUser()
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(this.userName, this.domainName, this.userPassword, LOGON32_LOGON_INTERACTIVE,
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;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
public void undoImpersonation()
{
impersonationContext.Undo();
}
#endregion
}
所以验证工作有效,但没有解决我的问题..我想权限仍然存在问题..我该怎么做才能改变这个?
EDIT 2:我接下来采取的步骤包括:
- 创建一个应用程序池,其中身份设置为用户(是管理员组的成员)。
- 将服务“登录”设置为同一用户。
- 再次运行网络应用程序后,仍然失败。
However如果我将管理员帐户作为代码中的凭据放入,它就可以工作..(即使我没有在应用程序池和服务中使用管理员...)
换句话说,我可以使用管理员帐户获得我想要的东西,但不能使用我自己创建并拥有管理员权限的帐户。我仍然想用我自己创建的用户来完成这项工作,因为我认为提供管理员凭据不太安全。
顺便说一句,在我工作的服务器上,我有一个具有管理员权限的帐户,但不是“管理员”帐户。
EDIT 3:这越来越奇怪了。我现在似乎在工作但是:
- 没有模拟方法(它不起作用)。
- 我只是按照罗布说的做了。我有自己的应用程序池和我定义的用户。 Windows 服务也指定了该用户。 (用户获得“登录为服务”权利)
——有了这个,看来可行了。
- 但如果通过我的网站进行调试,我仍然会被拒绝访问。但如果只是通过浏览器及其 IP 访问我的网站,我就可以启动该服务。
把它们加起来:
- 模拟方法不起作用。
- 如果服务还指定了用户,则仅使用当前用户自行创建的应用程序池即可。但它在调试模式下不起作用(仍然拒绝访问)。
这篇文章越来越大,我想知道是否还有人真正阅读它。.但也许仍然有人可以向我提供任何细节?我担心它会在未来的某个地方再次失败..
任何评论将不胜感激!
弗洛里斯