java 无法为标识添加安全令牌,令牌uri = docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken

zvokhttg  于 2023-08-02  发布在  Java
关注(0)|答案(1)|浏览(111)

我正在尝试使用jax-ws调用Web服务。当我在下面遇到错误时,

<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>

字符串
我搜索了这个错误,发现它需要在头中输入userid/password。因此,为了在头文件中添加用户凭据,我实现了自定义处理程序。

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)
    {
        //
    }
    
}


我使用下面的代码插入自定义处理程序并调用WS。

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);


添加处理程序后,**当我独立运行Eclipse时,代码运行良好。但是当我在Weblogic上部署相同的代码时,它仍然抛出相同的错误。在日志中,我正在打印信封。当我在SoapUI中再次使用相同的信封(复制/粘贴)时,它工作得很好。**但是当部署在Weblogic上时,它就不工作了。
下面是定义的策略。

<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 Server版本:14.1.1.0.0
**服务器/主机:WebLogic服务器版本:10.3.6.0

我无法理解这种行为,有没有人能帮我解决这个问题?

izkcnapc

izkcnapc1#

终于解决了这个问题。

  • 已完全删除自定义处理程序。
  • 而是修改了调用WS的代码
    之前
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);

字符串

现在(已更改/工作代码)

import weblogic.wsee.security.unt.ClientUNTCredentialProvider;
        import weblogic.xml.crypto.wss.WSSecurityContext;
        import weblogic.xml.crypto.wss.provider.CredentialProvider;
        import javax.xml.ws.BindingProvider;

        ManagementServices  service = new ManagementServices(webServiceUrl);
    
        Impl_ManagementServices port = service.getManagementServices();

        List<CredentialProvider> credProviders = new ArrayList<CredentialProvider>(); 
        CredentialProvider  cp = new ClientUNTCredentialProvider("username".getBytes(), "password".getBytes()); 
        credProviders.add(cp); 
        Map<String, Object> requestContext = ((BindingProvider) port).getRequestContext();
        requestContext.put(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);
    
            
        port.callingManageService(some_input);

相关问题