WebLogic 中的 JAX-WS 客户端 运行 中的 PasswordDigest 身份验证失败

PasswordDigest authentication fails in JAX-WS client running in WebLogic

我正在尝试实现一个使用 PasswordDigest 身份验证的 JAX-WS Web 服务客户端。

这是我的网络服务客户端:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.xml.ws.Binding;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.WebServiceRef;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.soap.AddressingFeature;

@Stateless
public class JaxWsService {

    /**
     * We cache the web service client, but on a thread local variable to avoid any potential multi-threading
     * issues.
     */
    private ThreadLocal<MyService> threadLocalClient = new ThreadLocal<MyService>();

    @WebServiceRef(wsdlLocation = "http://localhost:9999/mockMyService?WSDL")
    private MyServiceInterface service;

    @PostConstruct
    private void init() {
      AddressingFeature feature = new AddressingFeature(true, false);
      MyService proxy = service.getMyService(feature);

      List<Handler> handlerChain = new ArrayList<Handler>();
      //Add a handler to the handler chain
      handlerChain.add( new PasswordDigestHeaderHandler() );
      Binding binding = ( ( BindingProvider )proxy ).getBinding();
      binding.setHandlerChain(handlerChain);

      threadLocalClient.set(proxy);
    }

    public Response doSomething(String guid) {
      MyService client = threadLocalClient.get();
      return client.doSomething(guid);
  }
}

这是我的 SOAPHandler:

import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
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;

import ca.ns.gov.sns.rmv.util.PropertyUtil;
import sun.misc.BASE64Encoder;

public class PasswordDigestHeaderHandler implements SOAPHandler<SOAPMessageContext> {

  private static final String USERNAME = "username";
  private static final String PASSWORD = "password";
  private static DateFormat headerDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
  private static final String ENCODING_UTF_8 = "UTF-8";
  private static final String wssePrefix = "wsse";
  private static final String wsseURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
  private static final String wsuPrefix = "wsu";
  private static final String wsuURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; 

    @Override
    public boolean handleMessage(SOAPMessageContext context) {

        Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        if (outboundProperty.booleanValue()) {
            try {

                // Nonce
                SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
                rand.setSeed(System.currentTimeMillis());
                byte[] nonceBytes = new byte[16];
                rand.nextBytes(nonceBytes);

                // Created date
                headerDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                Calendar now = Calendar.getInstance();
                String createdDate = headerDateFormat.format(now.getTime());
                byte[] createdDateBytes = createdDate.getBytes(ENCODING_UTF_8);

                // Password
                byte[] passwordBytes = PASSWORD.getBytes(ENCODING_UTF_8);

                // SHA-1 hash the bunch of it.
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                baos.write(nonceBytes);
                baos.write(createdDateBytes);
                baos.write(passwordBytes);
                MessageDigest md = MessageDigest.getInstance("SHA-1");
                byte[] digestedPassword = md.digest(baos.toByteArray());

                // Encode the password and nonce                   
                String passwordB64 = (new BASE64Encoder()).encode(digestedPassword);
                String nonceB64 = (new BASE64Encoder()).encode(nonceBytes);

                now.add(Calendar.SECOND, 1000);
                String expiresTimestamp = headerDateFormat.format(now.getTime());

                SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
                SOAPFactory factory = SOAPFactory.newInstance();

                // Security
                SOAPElement securityE = factory.createElement("Security", wssePrefix, wsseURI);
                securityE.addNamespaceDeclaration(wssePrefix, wsseURI);
                securityE.addNamespaceDeclaration(wsuPrefix, wsuURI);
                securityE.addAttribute(new QName("mustUnderstand"), "1"); 

                // Security/Timestamp
                SOAPElement timestampE = factory.createElement("Timestamp", wsuPrefix, wsuURI);
                timestampE.setAttributeNS(wsuURI, "wsu:Id", "TS-" + generateRandomString());

                SOAPElement createdE = factory.createElement("Created", wsuPrefix, wsuURI);
                createdE.addTextNode(createdDate);
                timestampE.addChildElement(createdE);

                SOAPElement expiresE = factory.createElement("Expires", wsuPrefix, wsuURI);
                expiresE.addTextNode(expiresTimestamp);
                timestampE.addChildElement(expiresE);

                // Security/UsernameToken
                SOAPElement usernameTokenE = factory.createElement("UsernameToken", wssePrefix, wsseURI);
                usernameTokenE.setAttributeNS(wsuURI, "wsu:Id", "UsernameToken-" + generateRandomString());

                SOAPElement userE = factory.createElement("Username", wssePrefix, wsseURI);
                userE.addTextNode(USERNAME);

                SOAPElement pwdE = factory.createElement("Password", wssePrefix, wsseURI);
                pwdE.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
                pwdE.addTextNode(passwordB64);

                SOAPElement nonceE = factory.createElement("Nonce", wssePrefix, wsseURI);
                nonceE.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
                nonceE.addTextNode(nonceB64);

                usernameTokenE.addChildElement(userE);
                usernameTokenE.addChildElement(pwdE);
                usernameTokenE.addChildElement(nonceE);
                usernameTokenE.addChildElement(createdE);

                securityE.addChildElement(timestampE);
                securityE.addChildElement(usernameTokenE);

                SOAPHeader header = envelope.getHeader();

                if (header == null){
                    header = envelope.addHeader();
                }

                header.addChildElement(securityE);

                context.getMessage().saveChanges();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return outboundProperty;
    }

    @Override
    public Set<QName> getHeaders() {
        QName securityHeader = new QName(wsseURI, "Security", wssePrefix); 
        HashSet<QName> headers = new HashSet<QName>(); 
        headers.add(securityHeader);         
        return headers; 
    }

    @Override
    public void close(MessageContext context) {}

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return true;
    }

    /**
     * Generates a random string used in the Timestamp and UsernameToken elements.
     * 
     * @return
     */
    private String generateRandomString() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

...这些是由 ClientGenTask 生成的我的 Web 服务工件:

@WebServiceClient...
public class MyServiceInterface
    extends Service
{

...

@WebService...
@XmlSeeAlso({
    ObjectFactory.class
})
public interface MyService {

...这是网络服务的政策:

<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="wss_username_token_over_ssl_service_policy_PasswordDigest">
   <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
      <wsp:Policy>
         <sp:AlgorithmSuite>
            <wsp:Policy>
               <sp:Basic128/>
            </wsp:Policy>
         </sp:AlgorithmSuite>
         <sp:TransportToken>
            <wsp:Policy>
               <sp:HttpsToken RequireClientCertificate="false">
                  <wsp:Policy/>
               </sp:HttpsToken>
            </wsp:Policy>
         </sp:TransportToken>
         <sp:Layout>
            <wsp:Policy>
               <sp:Lax/>
            </wsp:Policy>
         </sp:Layout>
         <sp:IncludeTimestamp/>
      </wsp:Policy>
   </sp:TransportBinding>
   <sp:SupportingTokens 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:WssUsernameToken10/>
            </wsp:Policy>
         </sp:UsernameToken>
      </wsp:Policy>
   </sp:SupportingTokens>
</wsp:Policy> 

大部分代码取自我作为概念证明编写的独立应用程序,该应用程序运行良好。我能够访问 Web 服务并获得预期的响应。

但是当我将代码迁移到 Weblogic 12.1.3 中的 运行 时,我开始收到此错误:

Caused By: com.sun.xml.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: 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

是否需要通过 WebLogic 控制台完成一些设置才能从客户端启用 PasswordDigest,或者我是否遗漏了代码中的某些内容?

这是完整的堆栈跟踪:

Caused By: com.sun.xml.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: 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 Please see the server log to find more detail regarding exact cause of the failure.
    at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:193)
    at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:131)
    at com.sun.xml.ws.client.sei.StubHandler.readResponse(StubHandler.java:253)
    at com.sun.xml.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:203)
    at com.sun.xml.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:290)
    at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
    at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:92)
    at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:161)
    at com.sun.proxy.$Proxy367.retrieveDocumentRequest(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at weblogic.wsee.jaxws.spi.ClientInstanceInvocationHandler.invoke(ClientInstanceInvocationHandler.java:87)
    at com.sun.proxy.$Proxy365.retrieveDocumentRequest(Unknown Source)
    at com.myclient.project.services.ods.myservice.MyServiceSOAJaxWsService.retrieveDocument(MyServiceSOAJaxWsService.java:174)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    at com.oracle.pitchfork.intercept.MethodInvocationInvocationContext.proceed(MethodInvocationInvocationContext.java:100)
    at com.myclient.project.audit.AuditInterceptor.aroundInvoke(AuditInterceptor.java:50)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.oracle.pitchfork.intercept.JeeInterceptorInterceptor.invoke(JeeInterceptorInterceptor.java:109)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
    at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(Unknown Source)
    at com.sun.proxy.$Proxy358.retrieveDocument(Unknown Source)
    at com.myclient.project.services.ods.myservice.MyServiceSOAJaxWsService_elmy9k_myserviceServiceImpl.__WL_invoke(Unknown Source)
    at weblogic.ejb.container.internal.SessionLocalMethodInvoker.invoke(SessionLocalMethodInvoker.java:33)
    at com.myclient.project.services.ods.myservice.MyServiceSOAJaxWsService_elmy9k_myserviceServiceImpl.retrieveDocument(Unknown Source)
    at com.myclient.project.services.ods.MyServiceBean.retrieveDocument(MyServiceBean.java:347)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    at com.oracle.pitchfork.intercept.MethodInvocationInvocationContext.proceed(MethodInvocationInvocationContext.java:100)
    at com.myclient.project.audit.AuditInterceptor.aroundInvoke(AuditInterceptor.java:50)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.oracle.pitchfork.intercept.JeeInterceptorInterceptor.invoke(JeeInterceptorInterceptor.java:109)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
    at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
    at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(Unknown Source)
    at com.sun.proxy.$Proxy353.retrieveDocument(Unknown Source)
    at com.myclient.project.services.ods.MyService_tev81c_MyServiceImpl.__WL_invoke(Unknown Source)
    at weblogic.ejb.container.internal.SessionRemoteMethodInvoker.invoke(SessionRemoteMethodInvoker.java:34)
    at com.myclient.project.services.ods.MyService_tev81c_MyServiceImpl.retrieveDocument(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.invoke(RemoteBusinessIntfProxy.java:84)
    at com.sun.proxy.$Proxy151.retrieveDocument(Unknown Source)
    at com.myclient.project.web.ods.ODSRenderAttachment.init(ODSRenderAttachment.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.faces.vendor.WebContainerInjectionProvider.invokeAnnotatedMethod(WebContainerInjectionProvider.java:113)
    at com.sun.faces.vendor.WebContainerInjectionProvider.invokePostConstruct(WebContainerInjectionProvider.java:95)
    at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:223)
    at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:105)
    at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:408)
    at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:268)
    at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244)
    at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:103)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:179)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:224)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
    at javax.faces.component.UIOutput.getValue(UIOutput.java:170)
    at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:355)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:877)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1785)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1781)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1781)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:452)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
    at com.myclient.project.util.faces.CustomViewHandler.renderView(CustomViewHandler.java:63)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:604)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:346)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at com.myclient.project.util.SessionTimeoutFilter.doFilter(SessionTimeoutFilter.java:54)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at com.myclient.project.util.PersistenceFilter.doFilter(PersistenceFilter.java:86)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at com.myclient.project.util.UploadFilter.doFilter(UploadFilter.java:83)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at com.myclient.project.util.ClientTransactionConversationFilter.doFilter(ClientTransactionConversationFilter.java:34)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3436)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3402)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
    at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
    at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2285)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2201)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1572)
    at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:255)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)

奇怪的是,如果我通过 PasswordDigestHeaderHandler(如下)获取 XML 即 generated/output 并将其粘贴到 SoapUI 中,请求就可以工作。这似乎暗示缺少某些 WebLogic 配置。

<S:Envelope
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <env: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" mustUnderstand="1">
            <wsu:Timestamp wsu:Id="TS-6b8a287b7bf641f19b6841d555e9f380">
                <wsu:Created>2018-11-13T18:11:53.541Z</wsu:Created>
                <wsu:Expires>2018-11-13T18:28:33.541Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse:UsernameToken wsu:Id="UsernameToken-183099de358f4f0685eb34783a8b1c5c">
                <wsse:Username>username</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">42Nl15QHYJymbpxFDFC5kccoWuk=</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">9NTLR/h+GQQwRd1fQRxnqg==</wsse:Nonce>
                <wsu:Created
                    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2018-11-13T18:11:53.541Z
                </wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
    </env:Header>
    <S:Body>
        <RetrieveDocumentRequest
            xmlns="http://mycompany.com/MyService">
            ...
        </RetrieveDocumentRequest>
    </S:Body>
</S:Envelope>

尝试使用您的 init() 方法,您可能需要添加 WebLogic 凭证提供程序:

private void init() {
    AddressingFeature feature = new AddressingFeature(true, false);
    MyService proxy = service.getMyService(feature);

    List<Handler> handlerChain = new ArrayList<>();
    // Add a handler to the handler chain
    handlerChain.add(new PasswordDigestHeaderHandler());

    BindingProvider bindingProvider = (BindingProvider) proxy;
    Binding binding = bindingProvider.getBinding();
    binding.setHandlerChain(handlerChain);

    // weblogic.xml.crypto.wss.provider.CredentialProvider
    // weblogic.wsee.security.unt.ClientUNTCredentialProvider
    List<CredentialProvider> credProviders = new ArrayList<>();
    credProviders.add(new ClientUNTCredentialProvider(USERNAME.getBytes(), PASSWORD.getBytes()));

    Map<String, Object> context = bindingProvider.getRequestContext();
    // weblogic.xml.crypto.wss.WSSecurityContext
    context.put(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);
    // weblogic.security.SSL.TrustManager
    context.put(
        WSSecurityContext.TRUST_MANAGER,
        new TrustManager() {
            public boolean certificateCallback(X509Certificate[] chain, int validateErr) {
                return true;
            }
        }
    );

    threadLocalClient.set(proxy);
}

试试这个。

  1. 下载描述您的服务的 WSDL 文件并通过注释掉定义 wsp:PolicyReference: 的行来修改它。

  1. 将它放在一个文件夹中,该文件夹将包含在您的 jar/war/ear 文件中(例如 META-INF/wsdl)。

  2. 在您的 Web 服务客户端中,更改您的 @WebServiceRef 注入以引用此 local/bundled 版本的 WSDL:

    @WebServiceRef(wsdlLocation = "META-INF/wsdl/MyService.wsdl")
    private MyServiceInterface service;
    
  3. 将您的客户端初始化代码修改为如下所示:

    AddressingFeature feature = new AddressingFeature(true, false);
    MyService proxy = service.getMyService(feature);
    BindingProvider bindingProvider = (BindingProvider) proxy;
    
    List<Handler> handlerChain = new ArrayList<Handler>();
    //Add a handler to the handler chain
    handlerChain.add( new PasswordDigestHeaderHandler() );
    Binding binding = bindingProvider.getBinding();
    binding.setHandlerChain(handlerChain);
    
    // Add these two lines, to point to the remote service
    Map<String, Object> context = bindingProvider.getRequestContext();
    context.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, REMOTE_SERVICE_ENDPOINT);
    
    threadLocalClient.set(proxy);
    

... 其中 REMOTE_SERVICE_ENDPOINT 是您正在访问的远程 Web 服务的 URL。

应该可以了。您不必修改 PasswordDigestHeaderHandler 实现。

我在完全相同的问题上花了相当多的时间,但这个帖子让我走上了正确的道路:https://community.oracle.com/thread/2485783

祝你好运。