2012-09-05 47 views
5

我需要在新的Web服务中包含身份验证头(即作为SOAP头请求的一部分)。该身份验证头将验证userId和密码的详细信息。我必须验证我的Web Service中用于身份验证的请求标头详细信息的内容。如果通过身份验证,则会处理请求的SOAP正文,否则无效的身份验证消息将由Web服务发送回调用该服务的客户端应用程序。在SOAP中添加元素请求身份验证

我不能理解如何创建一个Web服务,其中的SOAP标题将包含一些元素(在我的情况下,认证元素,如userId和密码)。

通常,服务中公开的任何方法都将作为SOAP Body的一部分。因此,如何继续在SOAP Header中添加身份验证元素令人困惑。

请帮

问候,

+0

任何人都可以看看这个吗? https://stackoverflow.com/questions/43002576/soap-header-xmlnsds-on-each-element-for-xml-signature-generation –

回答

4

最近我写了一个类,它增加了用户凭据SOAP头。要做到这一点,你需要创建一个类实现SOAPHandler<SOAPMessageContext>接口。对于例如为:

public class MyHandler implements SOAPHandler<SOAPMessageContext> { 

    private static final Logger LOGGER = LoggerFactory.getLogger(MyHandler.class); 

    private String username; 

    private String password; 

    /** 
    * Handles SOAP message. If SOAP header does not already exist, then method will created new SOAP header. The 
    * username and password is added to the header as the credentials to authenticate user. If no user credentials is 
    * specified every call to web service will fail. 
    * 
    * @param context SOAP message context to get SOAP message from 
    * @return true 
    */ 
    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
     try { 
      SOAPMessage message = context.getMessage(); 
      SOAPHeader header = message.getSOAPHeader(); 
      SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); 
      if (header == null) { 
       header = envelope.addHeader(); 
      } 
      QName qNameUserCredentials = new QName("https://your.target.namespace/", "UserCredentials"); 
      SOAPHeaderElement userCredentials = header.addHeaderElement(qNameUserCredentials); 

      QName qNameUsername = new QName("https://your.target.namespace/", "Username"); 
      SOAPHeaderElement username = header.addHeaderElement(qNameUsername); 
      username.addTextNode(this.username); 
      QName qNamePassword = new QName("https://your.target.namespace/", "Password"); 
      SOAPHeaderElement password = header.addHeaderElement(qNamePassword); 
      password.addTextNode(this.password); 

      userCredentials.addChildElement(username); 
      userCredentials.addChildElement(password); 

      message.saveChanges(); 
      //TODO: remove this writer when the testing is finished 
      StringWriter writer = new StringWriter(); 
      message.writeTo(new StringOutputStream(writer)); 
      LOGGER.debug("SOAP message: \n" + writer.toString()); 
     } catch (SOAPException e) { 
      LOGGER.error("Error occurred while adding credentials to SOAP header.", e); 
     } catch (IOException e) { 
      LOGGER.error("Error occurred while writing message to output stream.", e); 
     } 
     return true; 
    } 

    //TODO: remove this class after testing is finished 
    private static class StringOutputStream extends OutputStream { 

     private StringWriter writer; 

     public StringOutputStream(StringWriter writer) { 
      this.writer = writer; 
     } 

     @Override 
     public void write(int b) throws IOException { 
      writer.write(b); 
     } 
    } 

    @Override 
    public boolean handleFault(SOAPMessageContext context) { 
     LOGGER.debug("handleFault has been invoked."); 
     return true; 
    } 

    @Override 
    public void close(MessageContext context) { 
     LOGGER.debug("close has been invoked."); 
    } 

    @Override 
    public Set<QName> getHeaders() { 
     LOGGER.debug("getHeaders has been invoked."); 
     return null; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 
} 

请注意,我只是添加凭据头和返回true。如果发生预期失败的情况,您可以用完整信息做任何事情并返回false

我已经实现了这一个客户端:

<bean id="soapHandler" class="your.package.MyHandler"> 
    <property name="username" value="testUser"/> 
    <property name="password" value="testPassword"/> 
</bean> 

<jaxws:client "..."> 
    <jaxws:handlers> 
     <ref bean="soapHandler"/> 
    </jaxws:handlers> 
</jaxws:client> 

但它也可以在endpoint实现。

+0

是的,它来自javax.xml.ws.handler.soap包。我不知道它是否可以用于JAX-RPC,我只用它与JAX-WS。您应该尝试查看它是否有效:) –

+1

以下是您应该阅读的有关IBM的JAX-RPC处理程序的链接:http://www.ibm.com/developerworks/webservices/library/ws-tipjax2/index.html –

+0

如果您有一个处理程序,并且您可以将该消息接收到该处理程序中,这意味着您可以对该消息执行任何操作。你只需要弄清楚如何修改RPC风格的消息。以下是通过JAX-RPC完成的示例:http://www.ibm.com/developerworks/xml/library/ws-tip-extend/index.html –

0

我们只能从信封中得到标题,而不能从肥皂信息中获得标题。