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