Java JBoss 401 Error on SharePoint 2010 Web Servic

2020-07-09 09:46发布

问题:

My code runs successfully when tested within the Eclipse IDE.

I'm connecting to MS SharePoint 2010 via Web Services using the generated Copy.wsdl

When I deploy my code on the JBoss server (Running Adobe LifeCycle) my code receives a 401 Error.

Error:

Caused by: org.jboss.ws.WSException: Invalid HTTP server response [401] - Unauthorized
at org.jboss.ws.core.soap.SOAPMessageUnMarshallerHTTP.read(SOAPMessageUnMarshallerHTTP.java:75)
at org.jboss.remoting.transport.http.HTTPClientInvoker.readResponse(HTTPClientInvoker.java:608)
at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:402)
at org.jboss.remoting.transport.http.HTTPClientInvoker.makeInvocation(HTTPClientInvoker.java:253)
... 156 more

Now if I purposely use the wrong login via the IDE I get this error:

com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 401: Unauthorized

Update:

So after more research it turns out J2EE support, well lack of, with NTLM is the cause. I've tried several solutions to no avail as of yet.

Code:

protected void initialize(String username, String password) throws Exception {
    System.out.println("initialize()...");
    java.net.CookieManager cm = new java.net.CookieManager();
    java.net.CookieHandler.setDefault(cm);
    Authenticator.setDefault(new SharepointAuthenticator(username, password));
}

Authenticator

public class SharepointAuthenticator extends Authenticator {

private String username = "";
private String password = "";

public SharepointAuthenticator(String username, String password) {
    this.username = username;
    this.password = password;
    System.out.println("Initializing Authentication");
}

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

Get SOAP

protected CopySoap getCopySoap(String username, String password, String wsdl, String endpoint) throws Exception {
    System.out.println("Creating a CopySoap instance...");
    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
    Copy service = new Copy(new URL(wsdl), new QName("http://schemas.microsoft.com/sharepoint/soap/", "Copy"));
    System.out.println("CopySoap 2");

    CopySoap copySoap = service.getCopySoap();

    System.out.println(endpoint + "\n" + wsdl);

    BindingProvider bp = (BindingProvider) copySoap;  
    bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
    bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
    bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
    return copySoap;
}

Call to upload file:

    // make the call to upload
    port.copyIntoItems("null", destinationUrlCollection, metadata, byteArray, longHolder, resultHolder);

回答1:

I am using CXF framework to create port. It will take care of all type of authentication. It is working in JBoss also.

It is simple to implement. Add CXF dependencies and use the following code to create port.

Sample Code :

InvocationHandlerImpl.java

public class InvocationHandlerImpl implements InvocationHandler
{
    CopySoap port;

    public InvocationHandlerImpl(CopySoap copySoap) {
        port = copySoap;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(port, args);
    }

}

TrustingX509TrustManager.java

public class TrustingX509TrustManager implements X509TrustManager
{
    /**
     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
     */
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // return null will let jsse accept all certificates!
        return null;
    }

    /**
     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
     */
    @Override
    public void checkClientTrusted(X509Certificate[] certs, String authType) {
    }

    /**
     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
     */
    @Override
    public void checkServerTrusted(X509Certificate[] certs, String authType) {
    }
}

SPCopyDriver.java

public class SPCopyDriver
{

    public static void main(String[] args) {

        JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
        proxyFactory.setServiceClass(CopySoap.class);
        proxyFactory.setUsername("domain\\username");
        proxyFactory.setPassword("password");
        proxyFactory.setAddress("https://<<IP>>/_vti_bin/Copy.asmx");

        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        httpClientPolicy.setAutoRedirect(true);
        httpClientPolicy.setAllowChunking(false);

        Object port = proxyFactory.create();
        Client client = ClientProxy.getClient(port);
        HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
        httpConduit.setClient(httpClientPolicy);

        TLSClientParameters tls = new TLSClientParameters();
        tls.setDisableCNCheck(true);
        tls.setTrustManagers(new TrustManager[] { new TrustingX509TrustManager() });
        httpConduit.setTlsClientParameters(tls);

        port = Proxy.newProxyInstance(SPCopyDriver.class.getClassLoader(), new Class[] { CopySoap.class }, new InvocationHandlerImpl((CopySoap) port));

        CopySoap copySoap = (CopySoap) port;

    }

}