Mil*_*les 5 asp.net security windows-services .net-2.0
我有一个网站,它启用了Windows身份验证.从网站中的页面,用户可以启动一项服务,该服务可以对数据库执行一些操作.
它适用于我启动服务,因为我是服务器上的本地管理员.但我只是有一个用户测试它,他们无法启动服务.
我的问题是:
有没有人知道如何通过名称使用与当前登录时不同的Windows帐户获取指定计算机上的服务列表?
我真的不想将需要启动服务的所有用户添加到一个Windows组中,并将它们全部设置为我的IIS服务器上的本地管理员.....
这是我得到的一些代码:
public static ServiceControllerStatus FindService()
{
ServiceControllerStatus status = ServiceControllerStatus.Stopped;
try
{
string machineName = ConfigurationManager.AppSettings["ServiceMachineName"];
ServiceController[] services = ServiceController.GetServices(machineName);
string serviceName = ConfigurationManager.AppSettings["ServiceName"].ToLower();
foreach (ServiceController service in services)
{
if (service.ServiceName.ToLower() == serviceName)
{
status = service.Status;
break;
}
}
}
catch(Exception ex)
{
status = ServiceControllerStatus.Stopped;
SaveError(ex, "Utilities - FindService()");
}
return status;
}
Run Code Online (Sandbox Code Playgroud)
我的例外来自try块中的第二行.这是错误:
System.InvalidOperationException:无法在计算机'server.domain.com'上打开服务控制管理器.此操作可能需要其他权限.---> System.ComponentModel.Win32Exception:拒绝访问---内部异常堆栈跟踪的结束---在System.ServiceProcess.ServiceController.GetServicesOfType(String)处的System.ServiceProcess.ServiceController.GetDataBaseHandleWithAccess(String machineName,Int32 serviceControlManaqerAccess)处telemarketingWebSite.Utilities.StartService()上的machineName,Int32 serviceType)
感谢您的帮助/信息
注意:这并不是将服务枚举为不同的用户,但考虑到您正在做的更广泛的描述,我认为这是一个很好的答案.
如果您直接访问感兴趣的服务,我认为您可以简化这一过程,并可能避免部分安全问题.试试这个,而不是调用GetServices:
string machineName = ConfigurationManager.AppSettings["ServiceMachineName"];
string serviceName = ConfigurationManager.AppSettings["ServiceName"];
ServiceController service = new ServiceController( serviceName, machineName );
return service.Status;
Run Code Online (Sandbox Code Playgroud)
这直接连接到感兴趣的服务并绕过枚举/搜索步骤.因此,它不需要调用者SC_MANAGER_ENUMERATE_SERVICE
在服务控制管理器(SCM)上拥有权限,默认情况下远程用户没有.它仍然需要SC_MANAGER_CONNECT
,但根据MSDN,应该授予远程认证用户.
一旦找到感兴趣的服务,您仍然需要能够停止并启动它,远程用户可能无权执行此操作.但是,可以修改单个服务上的安全描述符(DACL),这样您就可以授予远程用户访问权限以停止和启动服务,而无需他们成为本地管理员.这是通过SetNamedSecurityInfo API函数完成的.您需要授予的访问权限是SERVICE_START
和SERVICE_STOP
.根据这些用户所属的确切组,您可能还需要授予它们GENERIC_READ
.所有这些权利都在MSDN中描述.
这是一些将执行此设置的C++代码,假设感兴趣的用户位于"远程服务控制器"组(您将创建)中,并且服务名称为"my-service-name".请注意,如果您要授予对诸如用户(不一定是个好主意)之类的知名组的访问权限,而不是您创建的组,则需要更改TRUSTEE_IS_GROUP
为TRUSTEE_IS_WELL_KNOWN_GROUP
.
代码没有错误检查,您可以添加.可能失败的所有三个函数(Get/SetNamedSecurityInfo和SetEntriesInAcl)返回0表示成功.
另请注意:您还可以使用SC工具设置服务的安全描述符,该工具可以在%WINDIR%\ System32下找到,但不涉及任何编程.
#include "windows.h"
#include "accctrl.h"
#include "aclapi.h"
int main()
{
char serviceName[] = "my-service-name";
char userGroup[] = "Remote Service Controllers";
// retrieve the security info
PACL pDacl = NULL;
PSECURITY_DESCRIPTOR pDescriptor = NULL;
GetNamedSecurityInfo( serviceName, SE_SERVICE,
DACL_SECURITY_INFORMATION, NULL, NULL,
&pDacl, NULL, &pDescriptor );
// add an entry to allow the users to start and stop the service
EXPLICIT_ACCESS access;
ZeroMemory( &access, sizeof(access) );
access.grfAccessMode = GRANT_ACCESS;
access.grfAccessPermissions = SERVICE_START | SERVICE_STOP;
access.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
access.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
access.Trustee.ptstrName = userGroup;
PACL pNewDacl;
SetEntriesInAcl( 1, &access, pDacl, &pNewDacl );
// write the changes back to the service
SetNamedSecurityInfo( serviceName, SE_SERVICE,
DACL_SECURITY_INFORMATION, NULL, NULL,
pNewDacl, NULL );
LocalFree( pNewDacl );
LocalFree( pDescriptor );
}
Run Code Online (Sandbox Code Playgroud)
这也可以通过P/Invoke从C#完成,但这需要更多的工作.
如果您仍然特别希望能够以这些用户的身份枚举服务,则需要SC_MANAGER_ENUMERATE_SERVICE
在SCM上授予他们权限.不幸的是,根据MSDN,SCM的安全性只能在Windows Server 2003 sp1或更高版本上进行修改.
归档时间: |
|
查看次数: |
13916 次 |
最近记录: |