Web Services 使用SOAP WS返回错误401未授权

dojqjjoe  于 2022-11-15  发布在  其他
关注(0)|答案(4)|浏览(675)

我正在尝试使用spring-ws使用SOAP Web服务。我可以从SOAP UI成功使用此Web服务。但是我收到未经授权的异常错误:

org.springframework.ws.client.WebServiceTransportException: Unauthorized [401]
    at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:699)

如何成功进行身份验证?
我的代码如下:

Web服务模板配置:

@Bean
    public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller){
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setDefaultUri("http://ultron.illovo.net:9704/AdminService");
        webServiceTemplate.setMarshaller(marshaller);
        webServiceTemplate.setUnmarshaller(marshaller);

        Credentials credentials = new UsernamePasswordCredentials("biqa", "welcome1");

        HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
        messageSender.setCredentials(credentials);
        messageSender.setReadTimeout(5000);
        messageSender.setConnectionTimeout(5000);
        webServiceTemplate.setMessageSender(messageSender);

        return webServiceTemplate;
    }

客户:

@Autowired

WebServiceTemplate webServiceTemplate;

public CallProcedureWithResultsResponse callProcedureWithResults(String procedureName){
    CallProcedureWithResults request = new CallProcedureWithResults();
    request.setProcedureName(procedureName);
    log.info("Calling procedure " + procedureName);

    CallProcedureWithResultsResponse response = (CallProcedureWithResultsResponse) webServiceTemplate.marshalSendAndReceive("http://ultron.illovo.net:9704/AdminService/AdminService", request);

    return response;
}

JUnit测试

@Test
    public void testWebService(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ObieeConfiguration.class);
        ObieeClient client = context.getBean(ObieeClient.class);
        CallProcedureWithResultsResponse response = client.callProcedureWithResults("GetOBISVersion()");
        client.printResponse(response);
        context.close();
    }
gtlvzcf8

gtlvzcf81#

我通过执行以下操作解决了此问题:
创建HttpUrlConnectionMessageSender的子类,如下所示:

public class WebServiceMessageSenderWithAuth extends HttpUrlConnectionMessageSender {

    String user;
    String password;

    public WebServiceMessageSenderWithAuth(String user, String password) {
        this.user = user;
        this.password = password;
    }

    @Override
     protected void prepareConnection(HttpURLConnection connection) throws IOException { 
        BASE64Encoder enc = new BASE64Encoder(); 
        String userpassword = user+":"+password;
        String encodedAuthorization = enc.encode( userpassword.getBytes() ); 
        connection.setRequestProperty("Authorization", "Basic " + encodedAuthorization); 
        super.prepareConnection(connection); 
    } 

}

我的客户定义如下:

public class ObieeClient extends WebServiceGatewaySupport {

    private static final Logger log = LoggerFactory.getLogger(ObieeClient.class);

    public CallProcedureWithResultsResponse callProcedureWithResults(String procedureName, String webServiceURL){
        CallProcedureWithResults request = new CallProcedureWithResults();
        request.setProcedureName(procedureName);
        log.info("Calling procedure " + procedureName);

        CallProcedureWithResultsResponse response = (CallProcedureWithResultsResponse) ((JAXBElement) getWebServiceTemplate().marshalSendAndReceive(webServiceURL, request)).getValue();

        return response;
    }
}

最后,通过设置消息发送方,将客户端配置为使用凭据:

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();            marshaller.setContextPath("za.co.adaptit.smartdeployment.webservices.wsdl");

                //set up web service client
                ObieeClient client = new ObieeClient();
                client.setDefaultUri(host);
                client.setMarshaller(marshaller);
                client.setUnmarshaller(marshaller);
                client.setMessageSender(new WebServiceMessageSenderWithAuth("user", "password"));

response = client.callProcedureWithResults("NQSModifyMetadata('" + obieeObjectsXML +"')", server.getHost());

希望这对你有帮助。

moiiocjp

moiiocjp2#

我遇到了同样的问题,通过定义一个带有凭据的MessageSender,然后将其设置为客户端,我设法解决了这个问题。

@Bean
public WebServiceMessageSender messageSender(Credentials credentials) throws Exception{
    HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
    messageSender.setCredentials(credentials);
    return messageSender;
}

@Bean
public Credentials credentials(){
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(USERNAME, PASSWORD);
    return credentials;

}
unhi4e5o

unhi4e5o3#

使用HttpsUrlConnectionMessageSender进行安全的Https连接。这是spring-ws-support依赖关系的一部分。此外,您可以通过使用HttpsUrlConnectionMessageSender绕过各种证书颁发,例如证书公用名不匹配。
不要使用BASE64 Encoder,它是sun.misc jar的类,不太安全。使用java 1.8中存在的java util的Base64和低于java 1.8的java版本的apache的Base64

public class WebServiceMessageSenderWithAuth extends HttpsUrlConnectionMessageSender {

String user;
String password;

public WebServiceMessageSenderWithAuth(String user, String password) {
    this.user = user;
    this.password = password;
   }

@Override
 protected void prepareConnection(HttpURLConnection connection) throws IOException { 

    String userpassword = user+":"+password;
    String encodedAuthorization = Base64.encode( userpassword.getBytes() ); 
    connection.setRequestProperty("Authorization", "Basic " + encodedAuthorization); 
    //set various properties by using reference of connection according to your requirement
   } 
}
zazmityj

zazmityj4#

MessageSender必须是一个bean,因为它在其afterPropertiesSet方法中将凭据设置为底层HttpClient,只有当它是一个bean时,Spring才会自动调用该方法。https://github.com/spring-projects/spring-ws/blob/02cf3b7e2107d5ba728e9210cb705f31931c702a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponentsMessageSender.java#L221-L227
因此,在您的情况下,这种情况从未发生,您最终得到了一个没有凭据的HttpClient示例,这将正确地导致401。
其他方式包括:

  • 手动调用该方法
  • 使用凭据创建您自己的HttpClient,并将其设置为HttpComponentsMessageSender

但是我只将消息发送者定义为bean。

相关问题