2011-02-01 18 views
13

intento acceder a una lista de SharePoint a través de JAX-WS como se describe hereJAX-WS Sharepoint 401 NTLM no autorizado

Sin embargo, cuando se ejecuta el código de abajo me sale:

java.lang.Exception: Exception. See stacktrace.com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 401: Unauthorized 

Sharepoint requiere autenticación NTLM. ¿Cuál puede ser el problema? ¡Muchas gracias!

public static ListsSoap sharePointListsAuth(String userName, String password) throws Exception { 
    ListsSoap port = null; 
    if (userName != null && password != null) { 
     try { 
      Lists service = new Lists(); 
      port = service.getListsSoap(); 
      System.out.println("Web Service Auth Username: " + userName); 
      ((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, userName); 
      ((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password); 
     } catch (Exception e) { 
      throw new Exception("Error: " + e.toString()); 
     } 
    } else { 
     throw new Exception("Couldn't authenticate: Invalid connection details given."); 
    } 
    return port; 
} 

Respuesta

17

que estaba enfrentando el mismo problema al conectar con JAX-WS a los servicios web de Exchange, y esto es lo que funcionó para mí:

primer lugar, crear un autenticador:

import java.net.Authenticator; 
import java.net.PasswordAuthentication; 

public class NtlmAuthenticator extends Authenticator { 

    private final String username; 
    private final char[] password; 

    public NtlmAuthenticator(final String username, final String password) { 
    super(); 
    this.username = new String(username); 
    this.password = password.toCharArray(); 
    } 

    @Override 
    public PasswordAuthentication getPasswordAuthentication() { 
    return (new PasswordAuthentication (username, password)); 
    } 
} 

En su aplicación, configure el autenticador como el predeterminado:

String username = "DOMAIN\\USERNAME"; 
String password = "PASSWORD" 

NtlmAuthenticator authenticator = new NtlmAuthenticator(username, password); 
Authenticator.setDefault(authenticator); 

Tenga en cuenta que estoy utilizando el método n. ° 2 para especificar el dominio como se describe en el Java documentation.

+0

¿Es solo configuraciones para toda la aplicación? ¿Qué ocurre si necesito autenticar solo una solicitud en particular con esas credenciales? – glaz666

+0

Puede decir qué URL está solicitando las credenciales con getRequestingURL() dentro de su clase personalizada de Autenticador. Por lo tanto, puede devolver las credenciales en consecuencia. – jmend

+0

@MarcelLevy - ¿Dónde encaja el código que proporcionó con el código en la pregunta del OP? El enlace que proporcionó está ahora muerto ... – Joe

1

Hasta donde sé, no puede hacer la autenticación NTLM a través de BindingProvider.

Si está familiarizado con Spring framework, puede usar Spring-WS. Spring-WS admite transporte con Apache HttpClient 4.x a través de la clase HttpComponentsMessageSender. Apache HttpClient 4.x tiene un buen soporte para la autenticación NTLM. Puede usar las clases JAX-WS generadas por la herramienta wsimport como argumento en marshalSendAndReceive.

2

De acuerdo con mis conocimientos, anular los parámetros de BindingProvider NO establece el nombre de usuario y la contraseña requeridos. La forma más sencilla de probar esto es que no hay forma de pasar el nombre de dominio a través de la anulación de BP.

He visto varias publicaciones en Internet que sugieren una forma similar a la sugerencia de Marcel Levy de utilizar una instancia de autenticador NTLM (que es la forma definida según la documentación de JAVA 6 disponible de Oracle). Pero esta solución no funcionó para mí (estaba desarrollando un programa independiente independiente de cualquier lógica de servidor de aplicaciones).

Busqué en Google y probado muchas soluciones a este problema .. al parecer, el código más simple que funcionó es la siguiente usando la biblioteca JCIFS

//Set the jcifs properties 
    jcifs.Config.setProperty("jcifs.smb.client.domain", "domainname"); 
    jcifs.Config.setProperty("jcifs.netbios.wins", "xxx.xxx.xxx.xxx"); 
    jcifs.Config.setProperty("jcifs.smb.client.soTimeout", "300000"); // 5 minutes 
    jcifs.Config.setProperty("jcifs.netbios.cachePolicy", "1200"); // 20 minutes 
    jcifs.Config.setProperty("jcifs.smb.client.username", "username"); 
    jcifs.Config.setProperty("jcifs.smb.client.password", "password"); 

    //Register the jcifs URL handler to enable NTLM 
    jcifs.Config.registerSmbURLHandler(); 

Al parecer CXF 3.0 imposible tener una forma válida de configurar el cliente HTTP (4.3.x) con la instancia de NTCredentials. Por favor refiérase a error https://issues.apache.org/jira/browse/CXF-5671


Por cierto, si usted tiene un mensaje simple que se necesita transmitir, sólo tiene que utilizar cliente HTTP (trabajé usando 4.3.4 .. no está seguro de las versiones anteriores) con NTCredentials Ejemplo. Eso también hizo la magia para mí. La muestra es la siguiente:

final NTCredentials ntCredentials = new NTCredentials("username", "Passworrd","destination", "domain"); 
    CredentialsProvider credsProvider = new BasicCredentialsProvider(); 

    credsProvider.setCredentials(AuthScope.ANY, ntCredentials); 
    CloseableHttpClient httpclient = HttpClientBuilder.create() 
             .setDefaultCredentialsProvider(credsProvider) 
             .build(); 
Cuestiones relacionadas