更正 UsernameToken 和 CXF SOAP WS 的 WS-Policy

Correct WS-Policy for UsernameToken and CXF SOAP WS

我的 SOAP Web 服务上有以下注释:

@Policy(uri = "classpath:/ws/soap/UsernameTokenPolicy.xml")

这样的端点配置:

Map<String, Object> inProps = new HashMap<>();
inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
endpoint.getInInterceptors().add(wssIn);

endpoint.getProperties().put(SecurityConstants.USERNAME_TOKEN_VALIDATOR, authenticationPlugin);

这是UsernameTokenPolicy.xml的内容:

<?xml version="1.0" encoding="UTF-8"?>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
            xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
    <sp:SupportingTokens>
        <wsp:Policy>
            <sp:UsernameToken/>
        </wsp:Policy>
    </sp:SupportingTokens>
</wsp:Policy>

客户端发送这样的安全header:

  <soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <wsse:UsernameToken wsu:Id="UsernameToken-FA33408419A5268E38151818972919430">
        <wsse:Username>USERABC</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">123456789</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>

并且 CXF 服务器拒绝该策略:

org.apache.cxf.ws.policy.PolicyException: These policy alternatives can not be satisfied: 

    {http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SupportingTokens
    {http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}UsernameToken
        at org.apache.cxf.ws.policy.AssertionInfoMap.checkEffectivePolicy(AssertionInfoMap.java:179)

我不确定这里出了什么问题。根据 this document,我的政策看起来没问题(sp:IncludeToken 没有任何改变)。

感谢任何帮助。

我发现了问题,我需要策略感知拦截器作为第一个:

PolicyBasedWSS4JInInterceptor pwssIn = new PolicyBasedWSS4JInInterceptor();
endpoint.getInInterceptors().add(pwssIn);

Map<String, Object> inProps = new HashMap<>();
inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
endpoint.getInInterceptors().add(wssIn);

endpoint.getProperties().put(SecurityConstants.USERNAME_TOKEN_VALIDATOR, authenticationPlugin);