使用 Axis2 和 Rampart 使用 UsernameToken 配置文件 1.0 保护 Web 服务
Securing Web Service with UsernameToken profile 1.0 using Axis2 and Rampart
这是我在堆栈溢出中的第一个问题。
我不是专家 java 程序员,但我以前有使用该语言的经验和不同的 IDEs。
我有一个场景,客户要求我从给定的 WSDl 创建一个服务,必须 使用 UsernameToken Profile 1.0 OASIS Standard 200401 进行身份验证。它将受到保护生产服务器上的 ssl。
我一直在做一些研究并尝试实施不同的案例,但我发现没有任何东西适合我。
我正在使用:
- 以 Eclipse 为基础 IDE
- Axis2 V1.6.3
- 城墙 V1.6.2
- Rahas V1.6.2
为了说明目前的情况,这里我向您展示eclipse在从wsdl eclipse作为基础生成java bean服务结构时为我创建的结构IDE。
https://dl.dropboxusercontent.com/u/71031985/schema.png
已应用配置:
在 WebContent/WEB-INF/conf/axis2.xml 我启用 rampart 模块和 passwordCallbackClass 以便能够处理 soap headers.
中提供的用户名和密码
<module ref="rampart" />
<parameter name="InflowSecurity">
<action>
<items>UsernameToken</items>
<passwordCallbackClass>
serviceManager.ServiceAuthUserNameToken
</passwordCallbackClass>
<passwordType>PasswordText</passwordType>
</action>
</parameter>
...
在位于 /WebContent/WEB-INF/services/ProveedorCentroTFWS/META-INF/services.xml 的文件中,我放置了 rampart 策略以能够完成 usernametoken 要求:
<wsp:Policy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
</wsp:Policy>
</sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:passwordCallbackClass>serviceManager.ServiceAuthUserNameToken</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
当从客户提供的测试客户端执行调用时(无法修改),它会发送以下 soap 消息:
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<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" soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken-3">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">definedpwd</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:To>http://localhost:8080/ProveedorCentroTFWS</wsa:To>
<wsa:MessageID>urn:uuid:f2fb54d9-8957-49a2-88a7-de6d209e6d35</wsa:MessageID>
<wsa:Action>getActionList</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<ns3:getActionListxmlns:ns3="http://impl.ws.application.proveedorcentro.meyss.spee.es" />
</soapenv:Body>
发送 soap 消息后返回的错误如下:
java.lang.RuntimeException: Malformed uri: UsernameTokenPolicy
它遵循的堆栈跟踪是:
org.apache.neethi.PolicyReference.getRemoteReferencedPolicy(PolicyReference.java:155)
org.apache.neethi.PolicyReference.normalize(PolicyReference.java:110)
org.apache.axis2.util.PolicyUtil.getMergedPolicy(PolicyUtil.java:267)
org.apache.axis2.description.AxisBindingMessage.calculateEffectivePolicy(AxisBindingMessage.java:294)
org.apache.axis2.description.AxisBindingMessage.getEffectivePolicy(AxisBindingMessage.java:225)
org.apache.axis2.context.MessageContext.getEffectivePolicy(MessageContext.java:1617)
org.apache.rampart.RampartMessageData.<init>(RampartMessageData.java:233)
org.apache.rampart.MessageBuilder.build(MessageBuilder.java:61)
org.apache.rampart.handler.RampartSender.invoke(RampartSender.java:65)
org.apache.axis2.engine.Phase.invokeHandler(Phase.java:340)
org.apache.axis2.engine.Phase.invoke(Phase.java:313)
org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:262)
org.apache.axis2.engine.AxisEngine.sendFault(AxisEngine.java:516)
org.apache.axis2.transport.http.AxisServlet.handleFault(AxisServlet.java:433)
org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:216)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
我检查了一切和各种方法来尝试让它接受 soap 消息,但我无法让它工作。
感谢您的支持与关注
此问题的解决方案是所提供的 WSDL 遗漏了一些无法在 UsernameToken Profile 1.0 OASIS 标准 200401 下进行验证的部分。
在 IBM page 关于 WS-Security 和 Metro 下找到了解决方案。
在 WSDL 文档中,绑定标记下是策略引用:
<wsp:PolicyReference URI="#UsernameTokenPolicy" wsdl:required="true"/>
阅读在线文档我看到它指向任何地方,有必要在同一个 WSLD 文件中添加一个策略条目,就像下一个具有标识符名称 (#UsernameTokenPolicy) 或我们想要的策略的所需名称一样申请:
<wsp:Policy wsu:Id="UsernameTokenPolicy" xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken11 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
<wsss:ValidatorConfiguration wspp:visibility="private"
xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
<wsss:Validator name="usernameValidator" classname="[packageName].[callBackValidatorName]"/>
</wsss:ValidatorConfiguration>
</wsp:Policy>
完成后,您需要创建一个回调验证器,负责处理 SOAP 请求的 header 凭据,如下例所示:
package [packageName];
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
public class [callBackValidatorName] implements PasswordValidationCallback.PasswordValidator{
@Override
public boolean validate(PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest ptreq;
ptreq = (PasswordValidationCallback.PlainTextPasswordRequest) request;
return "[HARCODED_USERNAME]".equals(ptreq.getUsername()) &&
"[HARCODED_PWD]".equals(ptreq.getPassword());
}
}
完成所有这些后,您必须能够在服务器端的 Java Web 服务下验证与 UsernameToken Profile 1.0 OASIS Standard 200401 相匹配的 SOAP 消息。
这是我在堆栈溢出中的第一个问题。
我不是专家 java 程序员,但我以前有使用该语言的经验和不同的 IDEs。
我有一个场景,客户要求我从给定的 WSDl 创建一个服务,必须 使用 UsernameToken Profile 1.0 OASIS Standard 200401 进行身份验证。它将受到保护生产服务器上的 ssl。
我一直在做一些研究并尝试实施不同的案例,但我发现没有任何东西适合我。
我正在使用:
- 以 Eclipse 为基础 IDE
- Axis2 V1.6.3
- 城墙 V1.6.2
- Rahas V1.6.2
为了说明目前的情况,这里我向您展示eclipse在从wsdl eclipse作为基础生成java bean服务结构时为我创建的结构IDE。
https://dl.dropboxusercontent.com/u/71031985/schema.png
已应用配置:
在 WebContent/WEB-INF/conf/axis2.xml 我启用 rampart 模块和 passwordCallbackClass 以便能够处理 soap headers.
中提供的用户名和密码<module ref="rampart" />
<parameter name="InflowSecurity">
<action>
<items>UsernameToken</items>
<passwordCallbackClass>
serviceManager.ServiceAuthUserNameToken
</passwordCallbackClass>
<passwordType>PasswordText</passwordType>
</action>
</parameter>
...
在位于 /WebContent/WEB-INF/services/ProveedorCentroTFWS/META-INF/services.xml 的文件中,我放置了 rampart 策略以能够完成 usernametoken 要求:
<wsp:Policy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
</wsp:Policy>
</sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:passwordCallbackClass>serviceManager.ServiceAuthUserNameToken</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
当从客户提供的测试客户端执行调用时(无法修改),它会发送以下 soap 消息:
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<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" soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken-3">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">definedpwd</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:To>http://localhost:8080/ProveedorCentroTFWS</wsa:To>
<wsa:MessageID>urn:uuid:f2fb54d9-8957-49a2-88a7-de6d209e6d35</wsa:MessageID>
<wsa:Action>getActionList</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<ns3:getActionListxmlns:ns3="http://impl.ws.application.proveedorcentro.meyss.spee.es" />
</soapenv:Body>
发送 soap 消息后返回的错误如下:
java.lang.RuntimeException: Malformed uri: UsernameTokenPolicy
它遵循的堆栈跟踪是:
org.apache.neethi.PolicyReference.getRemoteReferencedPolicy(PolicyReference.java:155)
org.apache.neethi.PolicyReference.normalize(PolicyReference.java:110)
org.apache.axis2.util.PolicyUtil.getMergedPolicy(PolicyUtil.java:267)
org.apache.axis2.description.AxisBindingMessage.calculateEffectivePolicy(AxisBindingMessage.java:294)
org.apache.axis2.description.AxisBindingMessage.getEffectivePolicy(AxisBindingMessage.java:225)
org.apache.axis2.context.MessageContext.getEffectivePolicy(MessageContext.java:1617)
org.apache.rampart.RampartMessageData.<init>(RampartMessageData.java:233)
org.apache.rampart.MessageBuilder.build(MessageBuilder.java:61)
org.apache.rampart.handler.RampartSender.invoke(RampartSender.java:65)
org.apache.axis2.engine.Phase.invokeHandler(Phase.java:340)
org.apache.axis2.engine.Phase.invoke(Phase.java:313)
org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:262)
org.apache.axis2.engine.AxisEngine.sendFault(AxisEngine.java:516)
org.apache.axis2.transport.http.AxisServlet.handleFault(AxisServlet.java:433)
org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:216)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
我检查了一切和各种方法来尝试让它接受 soap 消息,但我无法让它工作。
感谢您的支持与关注
此问题的解决方案是所提供的 WSDL 遗漏了一些无法在 UsernameToken Profile 1.0 OASIS 标准 200401 下进行验证的部分。
在 IBM page 关于 WS-Security 和 Metro 下找到了解决方案。
在 WSDL 文档中,绑定标记下是策略引用:
<wsp:PolicyReference URI="#UsernameTokenPolicy" wsdl:required="true"/>
阅读在线文档我看到它指向任何地方,有必要在同一个 WSLD 文件中添加一个策略条目,就像下一个具有标识符名称 (#UsernameTokenPolicy) 或我们想要的策略的所需名称一样申请:
<wsp:Policy wsu:Id="UsernameTokenPolicy" xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken11 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
<wsss:ValidatorConfiguration wspp:visibility="private"
xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
<wsss:Validator name="usernameValidator" classname="[packageName].[callBackValidatorName]"/>
</wsss:ValidatorConfiguration>
</wsp:Policy>
完成后,您需要创建一个回调验证器,负责处理 SOAP 请求的 header 凭据,如下例所示:
package [packageName];
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
public class [callBackValidatorName] implements PasswordValidationCallback.PasswordValidator{
@Override
public boolean validate(PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest ptreq;
ptreq = (PasswordValidationCallback.PlainTextPasswordRequest) request;
return "[HARCODED_USERNAME]".equals(ptreq.getUsername()) &&
"[HARCODED_PWD]".equals(ptreq.getPassword());
}
}
完成所有这些后,您必须能够在服务器端的 Java Web 服务下验证与 UsernameToken Profile 1.0 OASIS Standard 200401 相匹配的 SOAP 消息。