2011-02-01 15 views
13

provo ad accedere a un elenco SharePoint tramite JAX-WS come descritto hereJAX-WS Sharepoint 401 NTLM non autorizzato

Tuttavia, quando si esegue il codice qui sotto ottengo:

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

Sharepoint richiede l'autenticazione NTLM. Quale potrebbe essere il problema? Molte grazie!

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

risposta

17

stavo affrontando lo stesso problema quando si collega con JAX-WS ai servizi web di Exchange, ed ecco cosa ha funzionato per me:

In primo luogo, creare un autenticatore:

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

Nella tua applicazione, impostare l'autenticatore come predefinito:

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

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

Nota che sto usando il metodo # 2 per specificare il dominio come descritto nello

+0

È solo l'installazione per l'intera applicazione? Cosa succede se ho bisogno di autenticare solo una richiesta particolare con quelle credenziali? – glaz666

+0

È possibile indicare quale URL richiede le credenziali con getRequestingURL() all'interno della classe Authenticator personalizzata. Pertanto, è possibile restituire le credenziali di conseguenza. – jmend

+0

@ MarcelLevy - Da dove viene inserito il codice fornito con il codice nella domanda dell'OP? Il link che hai fornito ora è morto ... – Joe

1

Per quanto ne so, non è possibile eseguire l'autenticazione NTLM tramite BindingProvider.

Se si ha familiarità con il framework Spring, è possibile utilizzare Spring-WS. Spring-WS supporta il trasporto con Apache HttpClient 4.x attraverso la classe HttpComponentsMessageSender. Apache HttpClient 4.x ha un buon supporto per l'autenticazione NTLM. È possibile utilizzare le classi JAX-WS generate dallo strumento wsimport come argomento su marshalSendAndReceive.

2

In base ai miei dati, ignorare i parametri di BindingProvider NON imposta il nome utente e la password richiesti. Il modo più semplice per provare questo è che non c'è modo di passare il nome del dominio attraverso l'override BP.

Ho visto più post su Internet suggerendo un modo simile al suggerimento di Marcel Levy in sopra di utilizzare un'istanza di autenticazione NTLM (che è il modo definito dalla documentazione di JAVA 6 disponibile da Oracle). Ma questa soluzione non ha funzionato per me (stavo sviluppando un programma standalone indipendente da qualsiasi logica del server delle applicazioni).

Ho cercato su google e ho provato un sacco di soluzioni a questo problema .. a quanto pare il codice più semplice che ha funzionato è come sotto utilizzando la libreria 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(); 

Apparentemente CXF 3.0 non ha una valida modo di configurazione il client HTTP (4.3.x) con l'istanza di NTCredentials. Si prega di fare riferimento al bug https://issues.apache.org/jira/browse/CXF-5671


A proposito, se si dispone di un semplice messaggio che deve essere trasmesso, basta usare client HTTP (ho lavorato utilizzando 4.3.4 .. Non sono sicuro delle versioni precedenti) con NTCredentials Esempio. Anche questo ha fatto la magia per me .. Il campione è il seguente:

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(); 
Problemi correlati