首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JAX-WS通过WS-Security和WS-Addressing使用web服务

JAX-WS通过WS-Security和WS-Addressing使用web服务
EN

Stack Overflow用户
提问于 2009-03-30 22:15:52
回答 3查看 41K关注 0票数 10

我正在尝试用JAX-WS (Metro)开发一个独立的Java web服务客户机,它使用WS-Security和用户名令牌身份验证(密码摘要、随机数和时间戳)和时间戳验证以及基于SSL的WS-Addressing。

我必须使用的WSDL没有定义任何安全策略信息。当WSDL不包含此信息时,我一直无法准确地确定如何添加此标头信息(正确的操作方法)。我发现使用Metro的大多数示例都是使用Netbeans从WSDL自动生成的,这对我一点帮助都没有。我研究过WSIT、XWSS等,没有太多的清晰和方向。JBoss WS Metro看起来也不太走运。

有没有人有这样做的经验,或者对如何完成这项任务有建议?即使给我指出正确的方向也是有帮助的。我不局限于一种特定的技术,除非它必须是基于Java的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-05-06 15:36:42

我最终解决了这个问题,但我走到了另一个方向。我的解决方案是使用CXF2.1及其JAX-WS实现,将CXF的强大功能与我已经就位的现有Spring基础设施结合起来。一开始我对此表示怀疑,因为CXF需要大量的jars,但最终它提供了最好和最简单的解决方案。

采用CXF website for client configuration中的一个示例,我在spring中使用了自定义的CXF JAXWS命名空间,并使用了一个Out Interceptor进行用户名令牌身份验证(密码摘要、随机数和时间戳)和时间戳验证。要实现这一点,唯一的另一个步骤是创建我自己的密码回调处理程序,该处理程序将为每个出站SOAP请求执行。

对于SSL配置,我再次求助于CXF and its SSL support via conduits,尽管我永远不能使SSL与特定的http:conduit名称一起工作,但我必须使用不推荐用于生产环境的通用名称。

下面是我的配置文件的一个示例。

Spring配置文件

代码语言:javascript
复制
<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>

客户端密码处理程序

代码语言:javascript
复制
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);
    }
}
票数 8
EN

Stack Overflow用户

发布于 2009-03-30 22:21:02

如果信息不在WSDL中,您确定它在WSDL所描述的服务中吗?WSDL旨在提供描述服务所需的所有信息,包括使用服务所需的安全策略。

WSDL来自什么平台?有没有可能WSDL不是完整的描述?例如,可能是_does提供安全信息的另一个WSDL中的include_d的WSDL。

票数 0
EN

Stack Overflow用户

发布于 2011-11-29 15:16:12

这里有一篇文章解释了如何在CXF中使用WS-Security配置客户机和服务器:JAX-WS Web Services with Spring and CXF

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/699254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档