WebLogic部署JAX-WS客户端遇UsernameToken安全令牌添加失败求助
JAX-WS调用WebService在WebLogic部署后仍报安全令牌错误问题
问题详情
调用WebService时收到如下SOAP错误响应:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope"> <faultcode>S:Server</faultcode> <faultstring>Unable to add security token for identity, token uri =http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</faultstring> <faultactor/> </S:Fault> </S:Body> </S:Envelope>
针对该错误,我实现了自定义SOAP Handler来添加用户名密码凭证,本地Eclipse独立运行代码时一切正常,但部署到WebLogic客户端后仍抛出相同错误。日志中打印的SOAP信封复制到SoapUI调用却能正常工作。
自定义Handler代码
import java.util.Set; import java.util.TreeSet; import javax.xml.namespace.QName; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPHeader; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; public class UsrSecHandler implements SOAPHandler<SOAPMessageContext> { private static final String AUTH_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; private static final String AUTH_PREFIX="wsse"; private String pwd; private String userName = null; private SOAPFactory mSoapFactory = null; public UsrSecHandler(String username, String password) { this.userName = username; this.pwd = password; } @Override public boolean handleMessage(SOAPMessageContext context) { Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outboundProperty.booleanValue()) { try { SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope(); if (mSoapFactory == null) { mSoapFactory = SOAPFactory.newInstance(); } SOAPElement wsSecHeaderElm, userNameTokenElm, userNameElm, passwdElm; // WSSecurity <Security> header wsSecHeaderElm = mSoapFactory.createElement("Security",AUTH_PREFIX,AUTH_NS); userNameTokenElm = mSoapFactory.createElement("UsernameToken",AUTH_PREFIX,AUTH_NS); userNameElm = mSoapFactory.createElement("Username",AUTH_PREFIX,AUTH_NS); passwdElm = mSoapFactory.createElement("Password",AUTH_PREFIX,AUTH_NS); userNameElm.addTextNode(this.userName); passwdElm.addTextNode(this.pwd); userNameTokenElm.addChildElement(userNameElm); userNameTokenElm.addChildElement(passwdElm); // add child elements to the root element wsSecHeaderElm.addChildElement(userNameTokenElm); // create SOAPHeader instance for SOAP envelope SOAPHeader header = envelope.getHeader(); if (header == null) { header = envelope.addHeader(); } header.addChildElement(wsSecHeaderElm); } catch (SOAPException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } return true; } @Override public Set<QName> getHeaders() { return new TreeSet<QName>(); } @Override public boolean handleFault(SOAPMessageContext context) { return false; } @Override public void close(MessageContext context) { // } }
Handler配置与调用代码
ManagementServices service = new ManagementServices(webServiceUrl); Impl_ManagementServices port = service.getManagementServices(); final Binding binding = ((BindingProvider) port).getBinding(); List<Handler> handlerList = binding.getHandlerChain(); handlerList.add(new UsrSecHandler(LOGIN, PASS)); binding.setHandlerChain(handlerList); port.callingManageService(some_input);
服务端安全策略
<wsp:Policy wssutil:Id="UsernameToken"> <ns1:SupportingTokens xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512"> <wsp:Policy> <ns1:UsernameToken ns1:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <ns1:WssUsernameToken10/> </wsp:Policy> </ns1:UsernameToken> </wsp:Policy> </ns1:SupportingTokens> </wsp:Policy>
环境信息
- 客户端WebLogic版本:14.1.1.0.0
- 服务端WebLogic版本:10.3.6.0
解决方案建议
1. 避免WebLogic内置JAX-WS实现覆盖自定义逻辑
WebLogic 14c自带的WS-Security实现可能会修改自定义Handler添加的Security头,可通过weblogic.xml配置让应用优先使用自身的JAX-WS依赖:
<weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"> <wls:container-descriptor> <wls:prefer-application-packages> <wls:package-name>javax.xml.ws.*</wls:package-name> <wls:package-name>com.sun.xml.ws.*</wls:package-name> <wls:package-name>com.sun.xml.bind.*</wls:package-name> </wls:prefer-application-packages> </wls:container-descriptor> </weblogic-web-app>
2. 调整Handler执行顺序
确保自定义Handler在WebLogic内置Handler之前执行,修改Handler添加逻辑:
// 插入到Handler链的第一个位置 handlerList.add(0, new UsrSecHandler(LOGIN, PASS)); binding.setHandlerChain(handlerList);
3. 完善UsernameToken的属性配置
服务端策略要求WssUsernameToken10,需补充必要的属性(比如wsu:Id和密码类型),修改Handler代码:
// 添加wsu命名空间定义 private static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; private static final String WSU_PREFIX = "wsu"; // 创建UsernameToken时添加Id属性 userNameTokenElm = mSoapFactory.createElement("UsernameToken", AUTH_PREFIX, AUTH_NS); userNameTokenElm.addAttribute(new QName(WSU_NS, "Id", WSU_PREFIX), "UsernameToken-1"); // 给Password元素添加明文密码类型属性 passwdElm.addAttribute(new QName("Type"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
4. 验证Handler是否实际执行
在handleMessage方法中添加日志输出,确认部署到WebLogic后Handler是否被调用:
System.out.println("Custom UsrSecHandler executed for outbound message");
如果未执行,可尝试通过weblogic-jaxws.xml配置文件注册Handler,而不是代码动态添加:
<weblogic-jaxws xmlns="http://xmlns.oracle.com/weblogic/weblogic-jaxws"> <client> <port-info> <port-name>ManagementServicesPort</port-name> <handler-chain> <handler> <handler-name>UsrSecHandler</handler-name> <handler-class>com.yourpackage.UsrSecHandler</handler-class> <init-param> <param-name>username</param-name> <param-value>your_login</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>your_pass</param-value> </init-param> </handler> </handler-chain> </port-info> </client> </weblogic-jaxws>
5. 检查WebLogic客户端安全配置冲突
确认WebLogic客户端是否配置了其他WS-Security策略(比如在weblogic-jaxws.xml或控制台中),这些配置可能会和自定义Handler冲突,暂时移除相关配置后再测试。
内容的提问来源于stack exchange,提问作者Atif Sheikh
相关产品推荐
相关产品推荐

