Pergunta

no meu site (escrito em ASP.NET/C#) quero que os moderadores possam iniciar um determinado serviço.O código que tenho para isso é:

    ServiceController svcController = new ServiceController("InvidualFileConversion");

    if (svcController != null)
    {
        try
        {
            svcController.Stop();
            svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
            svcController.Start();
        }
        catch (Exception ex)
        {
            // error
        }
    }

Agora, quando executo isso, recebo o erro "Não é possível abrir o serviço InvidualFileConversion no computador", com a mensagem adicional:"Acesso negado".

Eu sei que isso é um problema com permissões, mas como posso me conceder as permissões adequadas?Não venha com a resposta onde devo escrever:, porque eu tentei e não funcionou.Além disso, acho que essa não é a melhor maneira de configurar isso para todo o site, quando preciso apenas dessas poucas linhas de código.

EDITAR: Adicionei isso no meu código e ainda não funciona, recebo a mesma exceção no mesmo lugar.Agora fica assim:

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
        }
    }
}

Eu tenho uma classe Impersonate que se parece com isso:

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
}

Então a coisa da validação funciona, mas não resolve o meu problema.Acho que ainda há o problema com as permissões.O que eu faço para mudar isso?

EDITAR 2: As próximas etapas que tomei envolvem o seguinte:

  1. Criação de um pool de aplicativos em que a identidade é definida para um usuário (que é membro de um grupo de administradores).
  2. Defina o serviço "logon" para o mesmo usuário.
  3. Depois de executar o aplicativo da web novamente, ele ainda falha.

No entanto Se eu colocar a conta do Administrador como credenciais no código, funciona.(Mesmo não tendo utilizado o Administrador no App Pool e no serviço...)

Em outras palavras, posso conseguir o que desejo com a conta de administrador, mas não com uma conta que eu mesmo criei e que tenha direitos de administrador.Ainda quero fazer isso funcionar com um usuário que eu mesmo criei, pois acho que não é tão seguro disponibilizar suas credenciais de administrador.

Por outro lado, no servidor em que trabalho, tenho uma conta que possui privilégios de administrador, mas não é a conta de 'Administrador'.

EDITAR 3: Isso está ficando estranho.Parece que estou trabalhando agora, MAS:- sem o método de representação (não funcionou).- Acabei de fazer o que Rob disse.Tenho meu próprio pool de aplicativos com um usuário que defini.O serviço do Windows também tem esse usuário especificado.(O usuário recebeu logon como serviço direito) - Com isso, parece funcionar.- Mas se depurar através do meu site ainda recebo acesso negado.Mas se apenas acessar meu site através do navegador e seu ip posso iniciar o serviço.

Resumindo:- O método de representação não funciona.- Apenas usar um pool de aplicativos criado por você mesmo com o usuário atual funciona se o serviço tiver o usuário também especificado.Mas não funciona no modo de depuração (ainda Acces Denied lá).

Este post está ficando grande e me pergunto se alguém ainda o lê.Mas talvez alguém ainda possa me fornecer detalhes?Receio que falhe novamente em algum lugar no futuro.

Qualquer comentário será apreciado!Floris

Foi útil?

Solução

Você deve ter certeza de que seu site está sendo executado por um usuário que tenha direitos suficientes para iniciar o serviço.Certifique -se também de que a autenticação anônima esteja desativada no IIS de uma boa maneira de criar um usuário que tenha direitos para iniciar o serviço na web do servidor e, em seguida, criar um pool de aplicativos que seja executado nesse usuário. Então você precisa fazer com que seu site use Esse pool de aplicativos.Usando esta abordagem, todo o site será executado sob o usuário que você acabou de criar.Se quiser ser mais granular, você ainda pode criar o usuário que tem os direitos para iniciar o serviço, mas em vez de usá-lo para o pool de aplicativos, você pode fazer apenas a página que precisa para iniciar o serviço ser executada sob esse usuário usando a representação.Você pode usar o recurso de importação apenas para este método!

para mais detalhes dê uma olhada nos links abaixo:

http://forums.asp.net/t/1137962.aspx/1

http://support.microsoft.com/kb/306158

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top