Pergunta

Eu tenho alguns métodos que precisam ser executados como uma determinada conta de serviço, então faço a coisa normal:

public DoSomeWorkAsServiceAccount() {
    ...
    // assume I am given tokenHandle
    WindowsIdentity newId = new WindowsIdentity(tokenHandle); 
    WindowsImpersonationContext impersonatedUser = newId.Impersonate();

    ...
    // do the work here
    ...

    impersonatedUser.Undo();
}

Eu gostaria de evitar escrever esse código em todos os métodos, então estava pensando em criar um atributo personalizado:

[Impersonate(tokenHandle)]
public DoSomeWorkAsServiceAccount() {
    // do the work
}

Então, aqui estão as minhas questões:

  1. Isso é possível?
  2. Você pode me mostrar algo que evitará a duplicação de código?

Desde já, obrigado.

Foi útil?

Solução

Não acho que um atributo seja a melhor maneira de implementar um recurso como esse. Na maioria das vezes, os atributos agem apenas como metadados em tipos e membros (de lado as coisas orientadas para aspectos). Você precisaria escrever algo para verificar esse atributo e redirecionar a chamada do método de acordo. Se você já possui algum código de AOP em vigor, isso não deve ser uma tarefa árdua, mas se não tiver, provavelmente será muito melhor servido por algo assim:

public void DoWorkAsUser(tokenHandle, Action op)
{
  WindowsIdentity newId = new WindowsIdentity(tokenHandle); 
  WindowsImpersonationContext impersonatedUser = newId.Impersonate();

  op();

  impersonatedUser.Undo();
}

E então chame assim:

DoWorAsUser(token, MyMethod);

Isso permite que você centralize o código de representação sem ter que mexer com reflexão, co -escorvura etc.

Outras dicas

Eu não tenho nenhum código, mas você pode tentar usar PostSharp para fazer isso. Você pode criar um OnMethodinVocationAspect que organize o material de segurança antes de chamar o código do método. por exemplo

public class ImpersonateAttribute : OnMethodInvocationAspect
{
  public override void OnInvocation(MethodInvocationEventArgs eventArgs)
  {
    WindowsIdentity newId = new WindowsIdentity(tokenHandle); 
    WindowsImpersonationContext impersonatedUser = newId.Impersonate();

    eventArgs.Proceed() // Call the code in the actual method.

    impersonatedUser.Undo();
  }
}

O exposto acima é um palpite completo, mas, ao sugerir, posso ter lhe dado uma opção válida.

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