Dela via


Usando o Serviço de Repositório Seguro em um Provedor de Declarações Personalizadas com o SharePoint 2010

Recentemente, reparei um problema fora do comum ao usar o Serviço de Repositório Seguro (SSS) em um provedor de declarações personalizadas em que estava trabalhando.  Na realidade, esse é um cenário interessante porque eu estava fazendo o que muita gente quer fazer: aumento de declarações.  Eu precisava me conectar a uma fonte da dados remota para poder consultar informações adicionais sobre cada usuário e depois usar isso para determinar quais declarações aumentar ou não.

Como guia geral para usar fontes de dados em provedores de declarações personalizadas, é importante lembrar que o assembly do provedor de declaração personalizada continuará se mantendo ativado na memória pelo processo SharePoint STS.  Isso torna muito mais fácil a recuperação de "informações" (quer seja um conjunto de dados, um conjunto de credenciais, etc.) por meio do armazenamento delas em uma variável de nível de classe, e depois elas ficam disponíveis para uso até o próximo IISRESET.  A grande limitação aqui é que nem todos os recursos do farm do SharePoint podem estar disponíveis para você quando a classe do provedor de declaração personalizada for instanciada, e essa é a moral da história de hoje.

Nesse caso em particular, eu queria recuperar os dados do SSS do construtor para o meu provedor de declaração personalizada, e depois ia fazer outras coisas com eles; no meu caso, eu estava criando uma WindowsIdentity de um domínio em uma confiança unilateral para que eu pudesse usá-la para criar um contexto de representação com permissões para consultar o Active Directory remoto.  Onde o problema ocorreu foi quando eu tentei fazer uma coisa com a referência para o SSS no construtor e ela SEMPRE expirava.  Não importava qual método era chamado no SSS, ela simplesmente sempre falhava após 60 segundos com um erro de tempo limite.

Para consertar, bastou mover o código para fora do construtor.  O mesmo código exato funcionou perfeitamente quando chamado do override do método FillClaimsForEntity.  Foi por pura sorte e usando o método de tentativa e erro que eu descobri isso, então me pareceu uma boa dica para compartilhar.

Já que estamos falando sobre esse problema em particular (fazer logon em um domínio remoto e representação), então acho que vale a pena demonstrar um outro padrão que usei como solução, e uma pegadinha.

Conforme descrito acima, como o assembly permanece carregado no processo STS, é possível "manter ativadas" as variáveis de nível de classe.  Como por motivos óbvios eu não queria ficar fazendo logon repetidamente no domínio remoto quando precisava consultá-lo, criei uma variável de nível de classe para a minha WindowsIdentity.  O padrão ficou mais ou menos assim:

  1. Veja se já recuperou as credenciais SSS
    1. Caso negativo, execute o código que:
      1. Recupera as credenciais do SSS
      2. Usa a API LogonUser para fazer logon no domínio remoto usando as credenciais do SSS
      3. Instancia a variável WindowsIdentity para que tenha as credenciais do usuário remoto
  2. Verifique se a variável WindowsIdentity é nula ou não
    1. Se não for, execute o código que:
      1. Cria uma nova instância de um WindowsImpersonationContext de WindowsIdentity.Impersonate()
      2. Consulta o domínio remoto
      3. Chama Undo em WindowsImpersonationContext

Esse padrão parece funcionar bem e é o melhor desempenho que eu consegui até agora.  Agora aqui está a pegadinha: você não quer chamar Impersonate() na instância WindowsIdentity e por isso NÃO chama Undo em WindowsImpersonationContext depois.  Se você não desfizer a representação, então pelo que sei o site não vai renderizar mais.  Adicione e o evento Undo e tudo voltará ao normal.

Esta é uma postagem de blog traduzida. Consulte o artigo original em Using Secure Store Service in a Custom Claims Provider with SharePoint 2010