私のWebサイト(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サービスを開くことができません」というエラーが表示され、「アクセスが拒否されました」という追加のメッセージが表示されます。
これが権限の問題であることは知っていますが、適切な権限を自分に与えるにはどうすればよいですか? 私が書くべき答えを持って来ないでください:、私がそれを試したのにそれがうまくいかなかったからです。また、これらの数行のコードで必要な場合は、これをWebサイト全体に設定するのに最適な方法ではないと思います。
編集:これをコードに追加しましたが、それでも機能しません。同じ場所で同じ例外が発生します。これで、次のようになります。
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
}
したがって、検証は機能しますが、問題は解決しません。権限にまだ問題があると思います。これを変更するにはどうすればよいですか。
編集2:私が取った次のステップはこれを含みます:
- IDがユーザー(管理者グループのメンバー)に設定されるアプリプールを作成します。
- サービスの「ログオン」を同じユーザーに設定します。
- Webアプリを再度実行した後も、失敗します。
ただし、コードにクレデンシャルとして管理者アカウントを入力すると、機能します。(アプリプールとサービスで管理者を使用しなかった場合でも...)
つまり、Administratorアカウントでは必要なものを取得できますが、自分で作成して管理者権限を持つアカウントでは取得できません。管理者の資格情報を利用できるようにするのはそれほど安全ではないと思うので、自分で作成したユーザーでこれを機能させたいと思っています。
ちなみに、私が作業しているサーバーには、管理者権限はあるが「管理者」アカウントではないアカウントがあります。
編集3:これは奇妙になっています。私は今は機能しているようですが:-偽装方法なしで(機能しませんでした)。-ロブが言ったことをやっただけです。定義したユーザーを持つ独自のアプリケーションプールがあります。Windowsサービスには、そのユーザーも指定されています。(ユーザーはサービスとしてログオンする権利を受け取りました)-これで、動作しているようです。-しかし、私のWebサイトでデバッグすると、アクセスが拒否されます。しかし、ブラウザとそのIPを介して自分のWebサイトにアクセスするだけで、サービスを開始できます。
要約すると:-なりすまし方法は機能しません。-サービスにユーザーも指定されている場合は、currectユーザーで自分で作成したアプリプールを使用するだけで機能します。ただし、デバッグモードでは機能しません(まだアクセスが拒否されています)。
この投稿は大きくなりつつあり、まだ実際に読んでいる人はいないかと思います。しかし、それでも誰かが私に詳細を教えてくれるでしょうか。将来どこかでまた失敗するのではないかと思います。
コメントをいただければ幸いです。フローリス