2009-07-29 72 views
5

Tengo un back-end VB6 para un sitio ASP clásico. Ese VB luego llama a un servicio web en el mismo servidor utilizando MSXML2.XMLHTTP. Esto funciona todos nuestros servidores menos uno. Si configuro el sitio del servicio web para que acepte el inicio de sesión anónimo, funcionará, sin embargo, si fuerzo solo la seguridad integrada, MSXML devuelve un error de acceso denegado.Acceso denegado utilizando MSXML

estoy usando código del ejemplo here.

Set objDom = CreateObject("MSXML2.DOMDocument") 
Set objXmlHttp = CreateObject("MSXML2.XMLHTTP") 

' Load XML 
objDom.async = False 
objDom.loadXML XmlBody 

' Open the webservice 
objXmlHttp.Open "POST", AsmxUrl, False 

' Create headings 
objXmlHttp.setRequestHeader "Content-Type", "text/xml; charset=utf-8" 
objXmlHttp.setRequestHeader "SOAPAction", SoapActionUrl 

' Send XML command 
objXmlHttp.send objDom.xml 

Editar: Siguiendo el consejo de AnthonyWJones Bajé la lista de verificación y que todavía no está funcionando. Usando Fiddler muestra una única solicitud con una respuesta 401. La pestaña de autenticación muestra:

No Proxy-Authenticate Header is present. 
WWW-Authenticate Header is present: Negotiate 
WWW-Authenticate Header is present: NTLM 

Sin embargo, noté un comportamiento extraño. Cuando llamo al sitio web usando las credenciales del usuario que ha iniciado sesión en el escritorio remoto, funcionará. Me sale negociar, desafío, luego un 200 y funcionará. ¿Alguna idea de por qué esto funcionaría cuando el usuario inicia sesión en el escritorio remoto pero no en otras ocasiones?

+1

¿Qué sistema operativo está ejecutando el cliente roto? ¿El nombre de host del servidor de destino es "simple" (¿contiene puntos?). De lo contrario, la asignación a la zona de Intranet se lleva a cabo a través de un script proxy (http://msdn.microsoft.com/en-us/library/bb250483(VS.85).aspx) y, por lo tanto, si su aplicación cliente no está No use el proxy por alguna razón, la asignación de zona fallaría y usted golpearía un comportamiento como este. – EricLaw

+0

Windows Server 2003 R2 es el sistema operativo que estoy usando. El nombre de host del servidor de destino es simple y no contiene puntos. Si navego al servicio web usando el navegador, aparece como la zona de intranet local.En Opciones de Internet -> Conexiones -> Configuración de LAN, ninguno de los 3 cuadros está marcado. ¿Tal vez está intentando usar una configuración diferente cuando el explorador no está cargado para ese usuario? – Ryan

Respuesta

3

Supongo que confía en la pila HTTP WinINET subyacente para presentar las credenciales actuales de los usuarios en el servidor cuando el servidor lo desafía con la seguridad integrada de Windows.

WinINET solo lo hará de forma predeterminada si considera que el servidor de host está en la zona de intranet. Incluso entonces es posible que la configuración de seguridad de la Zona de Intranet del usuario se haya ajustado para no permitirlo.

Intente acceder al sitio con un navegador desde la máquina del cliente cuando inicie sesión como el mismo usuario que ejecuta su aplicación VB6. ¿En qué zona considera que está el servidor? Si no es una Intranet, deberá agregar el host a la lista de sitios que pertenecen a la zona. Mientras está allí, abra la configuración de seguridad de las zonas y desplácese hacia abajo a la categoría Autenticación de usuario. El inicio de sesión debe configurarse como "Inicio de sesión automático solo en la zona de Intranet".

Editar: Según su comentario estas cosas están configuradas correctamente. Las pocas cosas que quisiera sería: -

  1. Compruebe que el servidor está estrictamente configurado para aceptar únicamente la seguridad integrada de Windows.
  2. Compruebe la configuración de proxy en la máquina, ¿se ha denegado el permiso de un problema con un servidor proxy?
  3. Use el ProgID "MSXML2.XMLHTTP.3.0" para asegurarse de que se está utilizando la versión correcta de la DLL de MSXML (algunas instalaciones de otras aplicaciones de terceros pueden dañar el registro que lleva a la versión anterior de MSXML).
  4. Instale Fiddler en la máquina y mire la conversación http cuando la aplicación VB6 intente la llamada. ¿Hay una sola respuesta 401? WinINET no usa las credenciales del usuario? ¿Hay 3 401 respuestas? WinINET ha intentado utilizar las credenciales actuales de los usuarios, pero el servidor no las acepta.

A este punto nos encontramos en el territorio de administración del sistema. Por ejemplo, si el seguimiento del violinista muestra que el intento de autenticación no utiliza NTLM, entonces usa una autenticación Kerberos, compruebe que el servidor y el cliente tengan relojes configurados en 5 minutos el uno del otro y el controlador de dominio.

Compruebe el registro de eventos de los servidores, es el servidor no puede contactar al controlador de dominio.

Coloque un simple.htm en el servidor con solo la seguridad integrada de Windows e intenta golpearlo desde el navegador, ¿eso tiene éxito?

+0

El servicio web se encuentra en la zona de intranet local y está configurado como "Inicio de sesión automático solo en la zona de intranet". ¿Alguna otra idea? – Ryan

+0

Gracias por su respuesta agregada. He actualizado mi pregunta con los resultados de tus pruebas. Si navego directamente al servicio web, funciona bien, solo tengo problemas cuando lo llamo desde la DLL de VB. – Ryan

0

Después de mirar todas las cosas AnthonyWJones sugirieron que encontré que podía usar la autenticación básica haciendo:

objXmlHttp.Open "POST", AsmxUrl, False, UserName, Password 

si permitiera seguridad integrada que trataría de negociar pero luego fallar y 401, pero aunque sólo sea básica la autenticación está permitida, se conectará. Esta no es mi primera opción, pero es una mejor solución que permitir el acceso anónimo. Dejaré esto abierto por un tiempo más largo en caso de que alguien pueda explicar cómo funciona la seguridad integrada, pero luego le daré la respuesta aceptada a AnthonyWJones ya que su lista de verificación es buena y me llevó a encontrar esta otra opción.

Fiddler fue muy útil para descubrir todo esto.

3

Probablemente sea demasiado tarde para responder a Ryan, pero otros pueden tener el mismo problema, así que publicaré esto: Tengo un desarrollador que está teniendo el mismo problema con MSXML2.XMLHTTP. Lo que pasa es que tengo muestras que hacen esto desde hace mucho tiempo, así que sé que usó para funcionar, pero ahora no ... ¿tal vez un error recientemente introducido? Confiábamos en la detección automática de Intranet local por la pila WinINET y luego la pila estaría dispuesta a hacer Windows Integrated. El sitio estaba en la lista de omisión de proxy, que con las opciones predeterminadas lo coloca en la Intranet local. Y, de hecho, cuando navega hacia el sitio y va a la pestaña de Configuración de seguridad, ve que la Intranet local está resaltada, por lo que parece estar funcionando. Sin embargo, MSXML2.XMLHTTP aún no está dispuesto a hacer Windows Integrado ... A menos que agregue directamente el sitio a la Intranet Local mediante los botones Sitios/Avanzados en la pestaña Seguridad.

Por lo tanto, mi conclusión es que ahora hay algún tipo de error en la pila de WinINET que trata automáticamente los sitios de Intranet local detectados de forma diferente a los que se agregaron directamente a la lista de Sitios. Lo curioso es que cuando navega por el sitio al, las cosas funcionan como se esperaba y Windows Integrated se usa automáticamente (incluso sin agregar sitios directamente): es solo el acceso programático a través de MSXML2.XMLHTTP que no funciona.

Finalmente, esto no es lo que terminamos haciendo: en su lugar utilizamos MSXML2.ServerXMLHTTP.6.0. Esa pila (WinHTTP) parece hacer las cosas bien, sin embargo, hay una advertencia: no usa la configuración de proxy de IE por defecto, por lo que tiene algunas opciones: use ProxyCfg (para XP y versiones anteriores) o NETSH para Vista y más tarde para importar la configuración del proxy de IE en la pila de WinHTTP. Lo malo de esto es la configuración adicional en cada máquina cliente (esta fue una aplicación de VB de clientes gordos). Lo que elegimos hacer en su lugar fue poner la siguiente justo antes de la Enviar:

HTTP.SetProxy 2, "myproxy.mydomain.com", "* .midominio.com"

Puesto que usted va a ir a un sitio mydomain, podría pensar que podría decir HTTP.SetProxy 0, para eludir el proxy, pero eso no funciona. La pila debe ser contada: "Tengo un proxy, pero lo puenteo para mi dominio, y por cierto, el sitio que voy a encontrar está en ese dominio, es decir, es una Intranet local".

+0

Gracias por la respuesta. Todavía me gustaría eventualmente alejarme de usar autenticación básica si es posible. – Ryan

Cuestiones relacionadas