Recientemente, mientras usaba el Servicio de almacenamiento seguro (SSS) en un proveedor de notificaciones personalizado en el que estaba trabajando, noté un giro inesperado. Se trata de un escenario realmente interesante, porque estaba haciendo lo que muchos usuarios desean hacer: aumentar las notificaciones personalizadas. Necesitaba conectarme a un origen de datos remoto para poder consultar información adicional acerca de cada usuario y, a continuación, usarla para determinar qué notificaciones aumentar.

Como regla general para usar orígenes de datos en proveedores de notificaciones personalizados, es importante recordar que el ensamblado del proveedor de notificaciones personalizado se mantiene en funcionamiento en la memoria mediante el proceso STS de SharePoint. De esta manera, es mucho más fácil recuperar "información" (independientemente de si se trata de un conjunto de datos, un conjunto de credenciales, etc.) al almacenarla en una variable de nivel de clase para que luego esté disponible para su uso hasta el siguiente IISRESET. La gran limitación es que no todos los recursos del conjunto o la granja de servidores de SharePoint estarán disponibles en el momento en que se cree la instancia del proveedor de notificaciones personalizado. Esa es la moraleja de la historia.

En este caso en particular, quería recuperar datos de SSS en el constructor para mi proveedor de notificaciones personalizado y, a continuación, iba a usarla para "realizar otras tareas". Quería crear una WindowsIdentity desde un dominio a través de una confianza unidireccional, para poder usarla para crear un contexto de suplantación con permisos para consultar el dominio remoto de Active Directory. El problema era que cuando intentaba realizar alguna tarea con mi referencia al SSS en el constructor, SIEMPRE se agotaba el tiempo de espera. No importaba qué método se llamara en SSS, siempre se generaba un error de tiempo de espera agotado después de los 60 segundos.

Para corregirlo, solo tuve que colocar el código fuera del constructor. El mismo código exacto funcionó perfectamente al invocarlo desde la invalidación del método FillClaimsForEntity. Fue simplemente cuestión de suerte, y de prueba y error hasta que encontré la solución, por lo que me pareció que era una buena sugerencia para compartir.

Ya que estamos hablando de este problema en particular (inicio de sesión en un dominio remoto y suplantación), probablemente sea útil mencionar otro modelo que obtuve a raíz de este inconveniente y otra trampa.

Como se describió anteriormente, debido a que el ensamblado permanece cargado en el proceso STS, puede "mantener en funcionamiento" las variables de nivel de clase. Dado que, obviamente, no deseaba iniciar sesión varias veces en el dominio remoto cuando necesitaba consultarlo, creé una variable de nivel de clase para mi WindowsIdentity. El modelo es similar a lo siguiente:

  1. Ver si ya he recuperado las credenciales de SSS
    1. De lo contrario, ejecutar el código que:
      1. Recupera las credenciales de SSS
      2. Usa la API LogonUser para iniciar sesión en el dominio remoto con las credenciales que obtuve de SSS
      3. Crear una instancia de la variable WindowsIdentity, de modo que tenga las credenciales del usuario remoto
  2. Comprobar si la variable WindowsIdentity es null
    1. De lo contrario, ejecutar el código que:
      1. Crea una nueva instancia de WindowsImpersonationContext desde WindowsIdentity.Impersonate()
      2. Consultar el dominio remoto
      3. Llamar a Undo en WindowsImpersonationContext

Este modelo parece funcionar bien y es todo el rendimiento que pude obtener hasta el momento. Ahora, esta es la trampa: NO debe llamar a Impersonate() en la instancia WindowsIdentity si, a continuación, NO llama a Undo en el WindowsImpersonationContext resultante. Si no deshace la suplantación, en mi experiencia, el sitio dejará de representarse. Al agregar la devolución de llamada Undo, todo vuelve a funcionar.

Esta entrada de blog es una traducción. Puede consultar el artículo original en Using Secure Store Service in a Custom Claims Provider with SharePoint 2010