【问题标题】:Apache CXF and WS-Security - Password CallbackApache CXF 和 WS-Security - 密码回调
【发布时间】:2012-11-18 17:11:11
【问题描述】:

我遵循了一些教程的混搭,但都不太成功!

我正在尝试让 Apache CXF 和 WS-Security 回调我的 Spring Security 身份验证器。一切都快要开始工作了,但在获取密码以使 Spring 安全性脱离 WS 回调时,我遇到了问题。

下面的 Handler 出错了,但 pc.getPassword() 为空。我希望这是在 Soap 中发送的密码,以便我可以将其传递给 spring

public class ServerPasswordCallback implements CallbackHandler {

public void handle(Callback[] callbacks) throws IOException, 
    UnsupportedCallbackException {

    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

    pc.setPassword( pc.getPassword() );
}

我的拦截器是这样设置的

 <bean id="wsAuthenticationInterceptor" class="com.olympus.viewtheworld.server.security.auth.WSAuthenticationInInterceptor">
    <constructor-arg index="0">
        <map key-type="java.lang.String" value-type="java.lang.Object">
            <entry key="action" value="UsernameToken" />
            <entry key="passwordType" value="PasswordText" />
            <entry key="passwordCallbackClass" value="com.olympus.viewtheworld.server.security.auth.ServerPasswordCallback" />
        </map>
    </constructor-arg>
    <property name="authenticationManager" ref="authenticationManager"/>
</bean>

 <jaxws:endpoint id="secureHelloService"
                 implementor="#secureHelloServiceImpl"
                 implementorClass="com.olympus.viewtheworld.server.service.Impl.SecureHelloServiceImpl"
                 address="/SoapService/secure/hello">
    <jaxws:serviceFactory>
        <ref bean="jaxws-and-aegis-service-factory" />
    </jaxws:serviceFactory>
    <jaxws:inInterceptors>
        <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
        <ref bean="wsAuthenticationInterceptor" />
    </jaxws:inInterceptors>
</jaxws:endpoint>

我从 SoapUI 发出的肥皂请求是

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://test/">
   <soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>rob2</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">passwordxx</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
   <soapenv:Body>
      <test:hello>
         <!--Optional:-->
         <hello>asdf</hello>
      </test:hello>
   </soapenv:Body>
</soapenv:Envelope>

版本明智的是 Spring 3.1 和 CXF 2.7.0

我需要做什么才能在 ServerPasswordCallback 类中看到“passwordxx”?是肥皂请求、配置还是错误?!

干杯, 抢

【问题讨论】:

    标签: java spring-security cxf ws-security


    【解决方案1】:

    org.apache.ws.security.handler.WSHandlerConstants.PW_CALLBACK_CLASS 上的文档看来,该方法应改为使用存储的密码调用pc.setPassword,以将用户提供的密码与作为参数进行比较,而不是用户提供的密码本身:

    这个标签是指CallbackHandler实现类,用于 获取密码。这个标签的值必须是一个类名 javax.security.auth.callback.CallbackHandler 实例。回调函数

    javax.security.auth.callback.CallbackHandler.handle(javax.security.auth.callback.Callback[])

    获取 org.apache.ws.security.WSPasswordCallback 对象的数组。 仅使用数组的第一个条目。该对象包含 用户名/键名作为标识符。回调处理程序必须设置 在返回之前与此标识符关联的密码或密钥。这 应用程序可以使用以下方法设置此参数:

    call.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, "PWCallbackClass");


    我正在使用org.apache.ws.security.validate.Validator 来检查所提供密码的有效性,并在那里设置 Spring 安全上下文:

    @Bean(name = "wssforjInInterceptor")
    public WSS4JInInterceptor wssforjInInterceptor() {
        // Configure how we ask for username and password
        Map<String, Object> props = new HashMap<>();
        props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
        props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    
        // Password callback
        props.put(WSHandlerConstants.PW_CALLBACK_REF, passwordCallbackHandler());
    
        // Validator registration
        Map<QName, Object> validators = new HashMap<>();
        String WSS_WSSECURITY_SECEXT_1_0_XSD = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
        QName qName = new QName(WSS_WSSECURITY_SECEXT_1_0_XSD, WSHandlerConstants.USERNAME_TOKEN, "");
        validators.put(qName, usernameTokenValidator());
        props.put(WSS4JInInterceptor.VALIDATOR_MAP, validators);
    
        WSS4JInInterceptor wss4jInInterceptor = new WSS4JInInterceptor(props);
        return wss4jInInterceptor;
    }
    

    我不确定这种方法是更好还是更差(我很感激对此的一些反馈),但也许它对下一个人遇到这个问题很有用。似乎缺乏关于如何集成 Spring 安全性和 CXF 的最新文档。

    【讨论】:

      【解决方案2】:

      好的,所以这不是理想的解决方案,希望稍后会有更好的答案,很可能是当我有更多时间看这个时。

      我使用正则表达式检查完整的数据包并提取密码字段。代码如下。稍后当我找到正确的方法时会更新,因为这绝对不是它!

       WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
              String mydata= pc.getRequestData().getMsgContext().toString();        
              Pattern pattern = Pattern.compile("<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">(.*?)<");
              Matcher matcher = pattern.matcher(mydata);
              if (matcher.find())
              {
                   pc.setPassword( matcher.group(1) );
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-02
        • 1970-01-01
        • 2019-01-21
        • 2012-02-29
        • 2011-12-07
        相关资源
        最近更新 更多