Tôi đã kết thúc tìm ra vấn đề này nhưng tôi đã đi theo một hướng khác để làm như vậy. Giải pháp của tôi là sử dụng CXF 2.1 và triển khai JAX-WS, kết hợp sức mạnh của CXF với cơ sở hạ tầng Spring hiện có mà tôi đã có sẵn. Tôi đã hoài nghi lúc đầu vì rất nhiều lọ được yêu cầu bởi CXF, nhưng cuối cùng nó cung cấp giải pháp tốt nhất và đơn giản nhất.
Áp dụng ví dụ từ CXF website for client configuration, tôi đã sử dụng không gian tên CXAX JAXWS tùy chỉnh trong mùa xuân và sử dụng Trình chặn bên ngoài cho Xác thực mã thông báo tên người dùng (Xác thực mật khẩu, nonces và dấu thời gian) và xác minh dấu thời gian. Bước duy nhất khác để thực hiện công việc này là tạo trình xử lý gọi lại mật khẩu của riêng tôi được thực thi cho mỗi yêu cầu SOAP gửi đi.
Đối với cấu hình SSL, tôi lại chuyển sang CXF and its SSL support via conduits, mặc dù tôi không bao giờ làm cho SSL hoạt động với tên http: conduit cụ thể, tôi phải sử dụng mục đích chung không được khuyến nghị cho môi trường sản xuất.
Dưới đây là ví dụ về tệp cấu hình của tôi.
tập mùa xuân cấu hình
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<context:property-placeholder location="meta/my.properties" />
<context:component-scan base-package="com.foo" />
<import resource="remoting.xml" />
<jaxws:client id="myWebService" address="${my.endpointAddress}"
serviceClass="com.foo.my.ServicePortType">
<!-- Testing only, adds logging of entire message in and out -->
<jaxws:outInterceptors>
<ref bean="TimestampUsernameToken_Request" />
<ref bean="logOutbound" />
</jaxws:outInterceptors>
<jaxws:inInterceptors>
<ref bean="logInbound" />
</jaxws:inInterceptors>
<jaxws:inFaultInterceptors>
<ref bean="logOutbound" />
</jaxws:inFaultInterceptors>
<!-- Production settings -->
<!--
<jaxws:outInterceptors> <ref bean="TimestampUsernameToken_Request" />
</jaxws:outInterceptors>
-->
</jaxws:client >
<!--
CXF Interceptors for Inbound and Outbound messages
Used for logging and adding Username token/Timestamp Security Header to SOAP message
-->
<bean id="logInbound" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean id="logOutbound" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
<bean id="TimestampUsernameToken_Request" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken Timestamp" />
<entry key="user" value="${my.group}.${my.userId}" />
<entry key="passwordType" value="PasswordDigest" />
<entry key="passwordCallbackClass" value="com.foo.my.ClientPasswordHandler" />
</map>
</constructor-arg>
</bean>
<!--
http:conduit namespace is used to configure SSL using keystores, etc
*.http-conduit works but CXF says its only supposed to be for temporary use (not production),
well until the correct way works, we're going to use it.
-->
<http:conduit name="*.http-conduit">
<http:tlsClientParameters
secureSocketProtocol="SSL">
<!--
<sec:trustManagers>
<sec:keyStore type="JKS"
password="${my.truststore.password}"
file="${my.truststore.file}" />
</sec:trustManagers>
-->
<sec:keyManagers keyPassword="${my.keystore.password}">
<sec:keyStore type="JKS"
password="${my.keystore.password}"
file="${my.keystore.file}" />
</sec:keyManagers>
<!-- Cipher suites filters specify the cipher suite to allow/disallow in SSL communcation -->
<sec:cipherSuitesFilter>
<sec:include>.*_WITH_3DES_.*</sec:include>
<sec:include>.*_EXPORT_.*</sec:include>
<sec:include>.*_EXPORT1024_.*</sec:include
<sec:include>.*_WITH_DES_.*</sec:include
<sec:exclude>.*_WITH_NULL_.*</sec:exclude
<sec:exclude>.*_DH_anon_.*</sec:exclude>
</sec:cipherSuitesFilter>
</http:tlsClientParameters>
</http:conduit>
</beans>
Java Khách hàng Mật khẩu Handler:
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.log4j.Logger;
import org.apache.ws.security.WSPasswordCallback;
/**
* <p>
* Provides a callback handler for use processing outbound/inbound SOAP messages.
* ClientPasswordHandler sets the password used in the WS-Security UsernameToken
* SOAP header.
*
* </p>
*
* Created: Apr 1, 2009
* @author Jared Knipp
*
*/
public final class ClientPasswordHandler implements CallbackHandler {
protected static Logger log = Logger.getLogger(ClientPasswordHandler.class);
private static final PropertyManager PROPS = PropertyManager.getInstance();
private static String PASSWORD = PROPS.getPassword();
private static boolean IS_PASSWORD_CLEAR = PROPS.getIsClearPassword();
/**
* Client password handler call back. This method is used to provide
* additional outbound (or could be inbound also) message processing.
*
* Here the method sets the password used in the UsernameToken SOAP security header
* element in the SOAP header of the outbound message. For our purposes the clear
* text password is SHA1 hashed first before it is hashed again along with the nonce and
* current timestamp in the security header.
*/
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
if(log.isDebugEnabled()) { log.debug("Setting password for UsernameToken"); }
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
// Check to see if the password is already Hashed via SHA1, if not then hash it first
if(IS_PASSWORD_CLEAR) {
synchronized(this) {
PASSWORD = PasswordDigestUtil.doPasswordDigest(PASSWORD);
IS_PASSWORD_CLEAR = false;
PROPS.setIsClearPassword(IS_PASSWORD_CLEAR);
PROPS.setPassword(PASSWORD);
PROPS.saveProperties();
}
}
pc.setPassword(PASSWORD);
}
}
Nguồn
2009-05-06 15:36:41
Hãy để tôi làm rõ, nó không có trong WSDL mà tôi đã được cấp quyền truy cập. Các tài liệu tôi có lỗ (không đề cập đến dấu thời gian) để exlusion thông tin WSDL sẽ không làm tôi ngạc nhiên. –
Vâng, bạn sẽ cần WSDL thực sự để gọi dịch vụ thực sự.Đó là tất cả về nó. –
Vì vậy, không có khả năng rằng WSDL lá này ra nhưng nó được thực hiện trên máy chủ? Máy chủ là Java (có thể là JBoss hoặc Websphere) sử dụng một số phiên bản của Axis. –