2009-05-26 37 views
6

Todo,token de contexto de seguridad no válido o caducado en el servicio web WCF

Tengo un servicio de WCF web (vamos llamado servicio "B") alojado en IIS utilizando una cuenta de servicio (VM, Windows 2003 SP2). El servicio expone un punto final que usa WSHttpBinding con los valores predeterminados a excepción de maxReceivedMessageSize, maxBufferPoolSize, maxBufferSize y algunos de los tiempos de espera que se han aumentado.

El servicio web ha sido probada usando la carga de prueba de Visual Studio marco de carga con alrededor de 800 usuarios concurrentes y superado con éxito todas las pruebas sin excepciones que son lanzadas. El proxy en la prueba unitaria ha sido creado desde la configuración.

Hay una aplicación de SharePoint que utilizan el servicio de servidor de búsqueda de Office SharePoint para llamar a los servicios web "A" y "B". La aplicación obtendrá datos del servicio "A" para crear una solicitud que se enviará al servicio "B". La respuesta proveniente del servicio "B" está indexada para la búsqueda. El proxy se crea mediante programación utilizando ChannelFactory.

Cuando el servicio "A" tarda menos de 10 minutos, las llamadas al servicio "B" se realizan con éxito. Pero cuando el servicio "A" tarda más tiempo (~ 20 minutos) las llamadas al servicio "B" arrojan la siguiente excepción:

Mensaje de excepción: Se recibió un error no asegurado o incorrectamente seguro de la otra parte. Consulte la FaultException interna para conocer el código de error y el detalle Mensaje de excepción interna: No se pudo procesar el mensaje. Esto es más probable porque la acción 'namespace/OperationName' es incorrecta o porque el mensaje contiene un token de contexto de seguridad no válido o caducado o porque hay una falta de coincidencia entre los enlaces. El token de contexto de seguridad no sería válido si el servicio abortó el canal debido a inactividad. Para evitar que el servicio interrumpa prematuramente las sesiones inactivas, aumente el tiempo de espera de recepción en el enlace del punto final del servicio.

Los valores de encuadernación son los mismos, el tiempo, tanto en el servidor y cliente-servidor de servicios web se sincroniza con el servicio de hora de Windows, la misma zona horaria.

cuando miro el servidor donde el servicio web "B" está instalado puedo ver los errores de seguridad siguientes se registran:

Fuente: Seguridad

Categoría: Inicio/Cierre

Evento ID : 537

usuario NT AUTHORITY \ SYSTEM

inicio de sesión:

Razón: Se ha producido un error durante el inicio de sesión

Tipo de la conexión: 3

Proceso de inicio de sesión: Kerberos

Paquete de autenticación: Kerberos

Código de estado: 0xC000006D

código de subestado: 0xC0000133

Después de leer algunos de los blogs en línea, el Sta El código de tu nombre significa STATUS_LOGON_FAILURE y el código de subestado significa STATUS_TIME_DIFFERENCE_AT_DC. pero ya he comprobado los relojes del servidor y del cliente y están sincronizados.

También noté que el token de seguridad parece estar en caché en algún lugar del servidor porque tienen otro proceso que llama al servicio web "B" usando la misma cuenta de servicio y obtiene datos la primera vez que se llama. Luego inician el proceso para actualizar los índices del servicio de búsqueda del servidor sharepoint de Office y falla. Entonces, si llamaron nuevamente al primer proceso, también fallará.

¿Alguien ha experimentado este tipo de problemas o tiene alguna idea?

Saludos,

--Damian

Respuesta

1

Lo que creo que está pasando aquí es que su canal es el tiempo de espera (como se sospecha).

Si he entendido bien, no es para dar servicio a las llamadas Un que el tiempo de espera, sino más bien para dar servicio a B, antes de llamar a su funcionamiento.

supongo que va a crear su canal de antes de llamar al servicio Un, en lugar de justo a tiempo (es decir, antes de llamar al servicio de B). Debe crear el canal (proxy, cliente de servicios) justo antes de que lo utilice como:

AResponse aResp = null; 
BResponse bResp = null; 
using (ServiceAProxy proxyA = new ServiceAProxy()) 
{ 
    aResp = proxyA.DoServiceAWork(); 
    using (ServiceBProxy proxyB = new ServiceBProxy()) 
    { 
     bResp = proxyB.DoOtherork(aResp); 
    } 
} 
return bResp; 

Sin embargo, creo, que una vez que llegue a que problema (B servicio el tiempo de espera), se dará cuenta de que el proxy de la aplicación sharepoint (que llamó al servicio A) expirará. Para resolver eso, es posible que desee cambiar su modelo de servicio de una solicitud-respuesta a un modelo de publicación-suscripción.

Con los servicios de larga ejecución, querrá que su aplicación sharepoint se suscriba al servicio A, y haga que el servicio A publique sus resultados cuando esté listo para hacerlo, sin importar cuánto tiempo lleve.

Programando WCF Services (O'Reilly) por Juval Lowey, tiene una gran explicación, e IDesign (empresa de Juval) publicó a great set of coding standards for WCF, así como el código de un gran Publish-Subscribe Framework.

Espero que esto ayude, Assaf.

5

10 minutos es el tiempo de espera de recepción predeterminado. Si tiene un proxy inactivo durante más de 10 minutos, el servidor anula la sesión de seguridad de ese proxy. Habilite el registro y verá esto en el registro de diagnóstico del servidor. El mensaje de error que informó coincide con este comportamiento. Busque en el archivo de diagnóstico de su sistema "SessionIdleManager". Si lo encuentras, lo anterior es tu problema.

Dale un giro y establece el establishSecurityContext = "false" para el cliente y el servidor.

3

No llame a la operación de servicio en una instrucción using. En lugar de utilizar un patrón como ...

client = new ServiceClient("Ws<binding>") 
try 
{ 
    client.Operation(x,y); 
    client.Close(); 
} 
catch() 
{ 
    client.Abort(); 
} 

No entiendo por qué esto funciona, pero me imagino que cuando el proxy se sale del ámbito de la instrucción using, Cerrar no se llama.A continuación, el servicio espera a que receiveTimeout (en el enlace) expire y luego cancela la conexión, lo que hace que las llamadas posteriores fallen.

+0

Dejé de trabajar con Usar la declaración para el servicio. Si necesito deshacerme de él, llame explícitamente ((IDispose) Service) .Dispose(); por fin –

+1

El problema con la sentencia using es que si tiene una excepción durante la llamada, la instrucción using llamará a Dispose() en el cliente, que llamará a Close() en el canal subyacente. Como la conexión ya tiene una falla, arrojará otra excepción y, por lo tanto, nunca aparecerá la primera excepción. – flayn

0

De hecho, he activado este error haciendo algo tonto. Tengo una prueba de unidad que modifica la fecha del sistema para probar algunas funciones basadas en el tiempo. Y creo que la diferencia de tiempo aparente entre cuando creé el contexto y cuando llamé a mi método (debido a los cambios en la fecha del sistema), provocó que algo expirara.

Cuestiones relacionadas