迁移到 CXF 3.2.7 -> 如何解决 SOAP RQ 处理期间密码相关的安全错误?
Migrating to CXF 3.2.7 -> How to solve the password related security error during SOAP RQ processing?
Context :我正在尝试将 Web 服务从 CXF 2.2.2 迁移到 CXF 3.2.7
问题:
Post 每当我尝试通过类似 SOAP UI 的软件针对我的网络服务触发以下基于 HTTP-POST SOAP 的请求时进行迁移 UI :
<SOAP-ENV:Header>
<wsse:Security SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="">
<wsse:Username>sampleUser</wsse:Username>
<wsse:Password>12345</wsse:Password>
<wsse:PartnerID>samplePartner</wsse:PartnerID>
</wsse:UsernameToken>
</wsse:Security>
<wsa:To>http://localhost:8080/sampleWs</wsa:To>
<wsa:Action>http://localhost:8080/sampleWs/sampleAction</wsa:Action>
<wsa:From>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:From>
</SOAP-ENV:Header>
我从 CXF 安全模块收到以下安全异常:
18:11:29,250 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http-127.0.0.1:8080-1) Interceptor for {http://ws.sampleWs.varun/}SampleWebService has thrown exception, unwinding now: org.apache.cxf.binding.soap.SoapFault: A security error was encountered when verifying the message
at org.apache.cxf.ws.security.wss4j.WSS4JUtils.createSoapFault(WSS4JUtils.java:234) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:341) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:176) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:87) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) [cxf-core-3.2.7.jar:3.2.7]
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [cxf-core-3.2.7.jar:3.2.7]
.
.
.
Caused by: org.apache.wss4j.common.ext.WSSecurityException: BSP:R4201: Any PASSWORD MUST specify a Type attribute
at org.apache.wss4j.common.bsp.BSPEnforcer.handleBSPRule(BSPEnforcer.java:57) [wss4j-ws-security-common-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.message.token.UsernameToken.checkBSPCompliance(UsernameToken.java:834) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.message.token.UsernameToken.<init>(UsernameToken.java:143) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.processor.UsernameTokenProcessor.handleUsernameToken(UsernameTokenProcessor.java:137) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.processor.UsernameTokenProcessor.handleToken(UsernameTokenProcessor.java:62) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:340) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:285) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
... 28 more
根本原因似乎是 wsse:password
标记中缺少属性。
我检查了安全 WS 规范:
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
我找不到 wsse:password
最新 CXF 所期望的强制类型属性。
注意 : CXF version 2.2.2
可以很好地处理相同的请求
问题 :
有没有办法阻止 CXF 放弃上述请求并允许它通过。
我环顾四周但找不到任何答案?有什么建议么 ?
或者修改 SOAP 请求是唯一的解决方案?
以上请求已被删除,因为正如@GPI 先前所述,CXF 试图强制执行基本安全规范 (http://www.ws-i.org/profiles/basicsecurityprofile-1.1.html) 的 R4201。
为了防止 CXF 强制执行此操作,我们可以使用 ws-security
和 wss4j
提供的配置常量来指示 CXF 停止强制执行。
解决方案 #1(使用 WSS4J 拦截器)
在您的 spring 配置文件中,您可以将 isBspCompliant
设置为 false
:
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackRef">
<ref bean="passwordCallback" />
</entry>
<entry key="isBSPCompliant" value="false"/>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
解决方案 #2(使用 JAX-WS)
在您的 spring 配置文件中,您可以将 ws-security.is-bsp-compliant
设置为 false
:
<jaxws:endpoint id="sample" implementor="sample.ws.SampleWebService" address="/SampleWebService">
<jaxws:properties>
<entry key="ws-security.is-bsp-compliant" value="false"/>
</jaxws:properties>
</jaxws:endpoint>
有关其他配置选项,您可以参考这些页面:
我遇到了同样的问题,发现 soap 请求中存在问题。
我能够通过添加解决它:
- soap:Envelope
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
中的以下属性
- wsse:Password中的以下属性
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
我的请求 header 看起来像这样
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tic="http://ticket.degroupage.atos.ma/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1">
<wsse:UsernameToken><wsse:Username>XXXX</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">XXXX</wsse:Password>
</wsse:UsernameToken>
</wsse:Security></soapenv:Header>
<soapenv:Body>
...
Context :我正在尝试将 Web 服务从 CXF 2.2.2 迁移到 CXF 3.2.7
问题: Post 每当我尝试通过类似 SOAP UI 的软件针对我的网络服务触发以下基于 HTTP-POST SOAP 的请求时进行迁移 UI :
<SOAP-ENV:Header>
<wsse:Security SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="">
<wsse:Username>sampleUser</wsse:Username>
<wsse:Password>12345</wsse:Password>
<wsse:PartnerID>samplePartner</wsse:PartnerID>
</wsse:UsernameToken>
</wsse:Security>
<wsa:To>http://localhost:8080/sampleWs</wsa:To>
<wsa:Action>http://localhost:8080/sampleWs/sampleAction</wsa:Action>
<wsa:From>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:From>
</SOAP-ENV:Header>
我从 CXF 安全模块收到以下安全异常:
18:11:29,250 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http-127.0.0.1:8080-1) Interceptor for {http://ws.sampleWs.varun/}SampleWebService has thrown exception, unwinding now: org.apache.cxf.binding.soap.SoapFault: A security error was encountered when verifying the message
at org.apache.cxf.ws.security.wss4j.WSS4JUtils.createSoapFault(WSS4JUtils.java:234) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:341) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:176) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:87) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) [cxf-core-3.2.7.jar:3.2.7]
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [cxf-core-3.2.7.jar:3.2.7]
.
.
.
Caused by: org.apache.wss4j.common.ext.WSSecurityException: BSP:R4201: Any PASSWORD MUST specify a Type attribute
at org.apache.wss4j.common.bsp.BSPEnforcer.handleBSPRule(BSPEnforcer.java:57) [wss4j-ws-security-common-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.message.token.UsernameToken.checkBSPCompliance(UsernameToken.java:834) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.message.token.UsernameToken.<init>(UsernameToken.java:143) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.processor.UsernameTokenProcessor.handleUsernameToken(UsernameTokenProcessor.java:137) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.processor.UsernameTokenProcessor.handleToken(UsernameTokenProcessor.java:62) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:340) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:285) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
... 28 more
根本原因似乎是 wsse:password
标记中缺少属性。
我检查了安全 WS 规范: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
我找不到 wsse:password
最新 CXF 所期望的强制类型属性。
注意 : CXF version 2.2.2
可以很好地处理相同的请求问题 : 有没有办法阻止 CXF 放弃上述请求并允许它通过。 我环顾四周但找不到任何答案?有什么建议么 ? 或者修改 SOAP 请求是唯一的解决方案?
以上请求已被删除,因为正如@GPI 先前所述,CXF 试图强制执行基本安全规范 (http://www.ws-i.org/profiles/basicsecurityprofile-1.1.html) 的 R4201。
为了防止 CXF 强制执行此操作,我们可以使用 ws-security
和 wss4j
提供的配置常量来指示 CXF 停止强制执行。
解决方案 #1(使用 WSS4J 拦截器)
在您的 spring 配置文件中,您可以将 isBspCompliant
设置为 false
:
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackRef">
<ref bean="passwordCallback" />
</entry>
<entry key="isBSPCompliant" value="false"/>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
解决方案 #2(使用 JAX-WS)
在您的 spring 配置文件中,您可以将 ws-security.is-bsp-compliant
设置为 false
:
<jaxws:endpoint id="sample" implementor="sample.ws.SampleWebService" address="/SampleWebService">
<jaxws:properties>
<entry key="ws-security.is-bsp-compliant" value="false"/>
</jaxws:properties>
</jaxws:endpoint>
有关其他配置选项,您可以参考这些页面:
我遇到了同样的问题,发现 soap 请求中存在问题。
我能够通过添加解决它:
- soap:Envelope
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
中的以下属性
- wsse:Password中的以下属性
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
我的请求 header 看起来像这样
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tic="http://ticket.degroupage.atos.ma/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1">
<wsse:UsernameToken><wsse:Username>XXXX</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">XXXX</wsse:Password>
</wsse:UsernameToken>
</wsse:Security></soapenv:Header>
<soapenv:Body>
...