2011-02-01 2 views
13

Je tente d'accéder à une liste de Sharepoint via JAX-WS comme décrit hereJAX-WS Sharepoint 401 NTLM non autorisée

Cependant, lors de l'exécution du code ci-dessous je reçois:

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

Sharepoint requiert une authentification NTLM. Quel peut être le problème? Merci beaucoup!

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; 
} 

Répondre

17

je faisais face au même problème lors de la connexion avec JAX-WS aux services Web Exchange, et voici ce qui a fonctionné pour moi:

d'abord, créez un authentificateur:

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)); 
    } 
} 

Dans votre application, configurez l'authentificateur en tant que valeur par défaut:

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

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

Notez que j'utilise la méthode 2 pour spécifier le domaine comme décrit dans le Java documentation.

+0

Est-ce que seules les configurations pour l'application entière? Que dois-je faire si je dois authentifier une demande particulière avec ces informations d'identification? – glaz666

+0

Vous pouvez déterminer quelle URL demande les informations d'identification avec getRequestingURL() dans votre classe Authenticator personnalisée. Ainsi, vous pouvez renvoyer des informations d'identification en conséquence. – jmend

+0

@MarcelLevy - Où le code que vous avez fourni correspond-il au code de la question de l'OP? Le lien que vous avez fourni est maintenant mort ... – Joe

1

Autant que je sache, vous ne pouvez pas effectuer l'authentification NTLM via BindingProvider.

Si vous êtes familiarisé avec Spring framework, vous pouvez utiliser Spring-WS. Spring-WS prend en charge le transport avec Apache HttpClient 4.x via la classe HttpComponentsMessageSender. Apache HttpClient 4.x prend bien en charge l'authentification NTLM. Vous pouvez utiliser les classes JAX-WS générées par l'outil wsimport comme argument au marshalSendAndReceive.

2

Basé sur mes apprentissages, le remplacement des paramètres BindingProvider ne définit PAS le nom d'utilisateur et le mot de passe requis. Le moyen le plus simple de prouver cela est qu'il n'y a aucun moyen de passer le nom de domaine à travers le remplacement de BP. J'ai vu plusieurs messages sur Internet suggérant une manière similaire à la suggestion de Marcel Levy ci-dessus d'utiliser une instance d'authentificateur NTLM (qui est la façon définie par la documentation JAVA 6 disponible auprès d'Oracle). Mais, cette solution ne fonctionnait pas pour moi (je développais un programme autonome indépendant de toute logique de serveur d'application).

Je googlé et essayé beaucoup de solutions à ce problème .. apparemment le code le plus simple qui fonctionne est comme ci-dessous à l'aide de la bibliothèque 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(); 

Apparemment CXF 3.0 ne marche pas avoir un moyen valable de configuration le client HTTP (4.3.x) avec l'instance NTCredentials. S'il vous plaît se référer à bug https://issues.apache.org/jira/browse/CXF-5671


Par ailleurs, si vous avez un message simple qui doit être transmis, il suffit d'utiliser le client HTTP (je travaillais à l'aide 4.3.4 .. pas sûr des versions antérieures) avec NTCredentials Exemple. Cela aussi fait la magie pour moi .. L'échantillon est comme ci-dessous:

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(); 
Questions connexes