9

사용자 이름 토큰 인증과 함께 WS-Security를 ​​사용하는 JAX-WS (Metro)를 사용하여 독립 실행 형 Java 웹 서비스 클라이언트를 개발하려고합니다 (비밀번호 다이제스트, nonces 타임 스탬프) 및 타임 스탬프 확인과 함께 SSL을 통한 WS-Addressing을 지원합니다.WS-Security 및 WS-Addressing을 사용하는 웹 서비스를 사용하는 JAX-WS

작업해야하는 WSDL은 보안 정책 정보를 정의하지 않습니다. WSDL에이 정보가 포함되어 있지 않을 때이 헤더 정보를 올바르게 추가하는 방법을 정확히 알 수 없었습니다. Metro를 사용하여 발견 한 대부분의 예제는 Netbeans를 사용하여 WSDL에서이를 자동으로 생성하므로 전혀 도움이되지 않습니다. 나는 WSIT, XWSS 등을 많은 명확성이나 방향없이 조사했다. JBoss WS Metro는 아직 운이 좋지는 않을 것으로 보입니다.

누구나이 작업을 수행했거나이 작업을 수행하는 방법에 대한 제안이 있습니까? 나를 올바른 방향으로 향하게조차 도움이 될 것입니다. 나는 Java 기반이 아닌 특정 기술에 국한되지 않습니다.

답변

8

나는이 문제를 알아내는 것을 끝내지 만 나는 그렇게 할 다른 방향으로 갔다. 내 솔루션은 CXF 2.1과 그 JAX-WS 구현을 사용하여 CXF의 힘과 기존의 기존 스프링 인프라를 결합하는 것이 었습니다. CXF가 요구하는 수많은 항아리 때문에 처음에는 회의적 이었지만 결국에는 가장 쉽고 간단한 솔루션을 제공했습니다.

CXF website for client configuration의 예제를 적용하여 봄에 사용자 정의 CXF JAXWS 네임 스페이스를 사용하고 Username Token Authentication (암호 요약, nonces 및 timestamp) 및 타임 스탬프 확인에 Out Interceptor를 사용했습니다. 이 작업을 수행하는 유일한 다른 단계는 각각의 아웃 바운드 SOAP 요청에 대해 실행되는 자체 암호 호출 처리기를 만드는 것입니다.

SSL 구성의 경우 특정 http : conduit 이름으로 SSL을 작동시킬 수는 없지만 다시 CXF and its SSL support via conduits으로 바뀌 었습니다. 프로덕션 환경에 권장되지 않는 일반적인 목적을 사용해야했습니다.

다음은 설정 파일의 예입니다.

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

자바 클라이언트 암호 처리기 스프링 설정 파일 :

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

정보가 WSDL에 없으면 WSDL에서 설명하는 서비스에 있는지 확인하십시오. WSDL은 서비스를 사용하는 데 필요한 보안 정책을 포함하여 서비스를 설명하는 데 필요한 모든 정보를 제공합니다.

WSDL은 어떤 플랫폼에서 왔습니까? WSDL이 완전한 설명이 아닌 것이 가능한가? 예를 들어 인 WSDL 일 수도 있고 다른 WSDL에 d를 포함하면 이 보안 정보를 제공합니다.

+0

WSDL에 액세스 권한이 없다는 것을 명확히 설명합니다. 내가 가지고있는 문서에는 구멍 (타임 스탬프에 대한 언급 없음)이 있으므로 WSDL 정보의 예외가 나를 놀라게하지는 않을 것입니다. –

+0

자, 실제 서비스를 호출하려면 실제 WSDL이 필요합니다.그게 전부입니다. –

+0

따라서 WSDL에서 제외되지만 서버에 구현 될 가능성은 없습니까? 서버는 Axis의 일부 버전을 사용하는 Java (아마도 JBoss 또는 Websphere)입니다. –

관련 문제