【问题标题】:Setting a custom cookie in the HTTP headers inside a SOAP Message handler在 SOAP 消息处理程序内的 HTTP 标头中设置自定义 cookie
【发布时间】:2013-08-03 02:14:39
【问题描述】:

我需要创建一个具有特定名称的 Cookie,以便在我的 Web 服务调用中发送到另一个网络,该网络具有基于它的路由逻辑。

当我尝试使用

在我的 SOAP 处理程序中设置 HTTP 标头时
headers.put("Cookie", Collections.singletonList(cookiename + "='" + cookieValue + "'")); 

它是第一次工作。

对此的响应带有 Set-Cookie for JSESSIONID

我的后续请求保留了 JSESSIONID 及其在 cookie 中的值,并忽略了设置我的自定义 cookie。

有没有办法确保在我的所有请求中默认设置我的 cookie?

【问题讨论】:

  • 也许您的 cookie 存储在 web 服务端点的数据库中,而服务器只给您一个会话 ID。顺便说一句,您是否尝试过自定义 HTTP 标头,例如“X-MyCustomHeader: my value”,而不是 Cookie 标头?

标签: java cookies http-headers soaphandler


【解决方案1】:

我们最近还需要通过 SOAP 服务支持 JSESSIONID,这是我们在阅读 StackOverflow 并参考 IBM 站点上的 SSO 客户端示例后得出的结论。

我们扩展了 SOAPHandler

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.List;

import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import com.sun.istack.internal.Nullable;

public class SoapMessageHandler implements SOAPHandler<SOAPMessageContext> {

    private String sessionCookie = "";

    @Override
    public void close(MessageContext arg0) { }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public Set getHeaders() {
        return null;
    }

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

    @Override
    public boolean handleMessage(SOAPMessageContext soapMessageContext) {
        if ((Boolean) soapMessageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {
            // Add header to outbound request (set cookie in HTTP client header)
            // Set the Cookie
            Map<String, List<String>> headers = (Map<String, List<String>>)soapMessageContext.get(MessageContext.HTTP_REQUEST_HEADERS);
            if (headers == null) {
                headers = new HashMap<String, List<String>>();
                soapMessageContext.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
            }
            List<String> cookie = headers.get("Cookie");
            if (cookie == null) {
                cookie = new ArrayList<String>();
                headers.put("Cookie", cookie);
            }
            cookie.add(sessionCookie);
        } else {
            // Read header from request (read cookie from server's HTTP headers)
            Map<String, List<String>> map = (Map<String, List<String>>) soapMessageContext.get(MessageContext.HTTP_RESPONSE_HEADERS);
            List<String> contentType = getHTTPHeader(map, "Set-Cookie");
            // Note, only grabs last cookie value!
            // If you need to present more than one cookie you could make
            // sessionCookie a List<String> and modify this class accordingly.
            if (contentType != null) {
                StringBuffer strBuf = new StringBuffer();
                for (String type : contentType) {
                    strBuf.append(type);
                }
                sessionCookie = strBuf.toString();
            }
        }
        return true;
    }

    private @Nullable List<String> getHTTPHeader(Map<String, List<String>> headers, String header) {
        for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
            String name = entry.getKey();
            if (header != null && name !=null) {
                if (name.equalsIgnoreCase(header))
                    return entry.getValue();
            }
        }
        return null;
    }

}

这也需要HandlerResolver

import java.util.ArrayList;
import java.util.List;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;

public class SoapHandlerResolver implements HandlerResolver {

@SuppressWarnings("unchecked")
public List<Handler> getHandlerChain(PortInfo portInfo) {
      List<Handler> handlerChain = new ArrayList<Handler>();
      handlerChain.add( new SoapMessageHandler() );
      return handlerChain;
   }
}

然后在调用 SOAP 服务时调用扩展的 HandlerResolver,如下所示:

ExampleService exampleService = new ExampleService();
exampleService.setHandlerResolver( new SoapHandlerResolver() );
Example example = exampleService.getExampleServicePort();
example.myMethod();

这适用于我们,使用 Java 6,但仅限于支持一个 Cookie 标头(尽管可以进行简单的修改以支持多个 Cookie 标头)。

注意:如果像我们一样,您必须在多个服务之间传递相同的会话 cookie(好像 SOAP 服务上的 cookie 还不够糟糕),而不是这样:

private String sessionCookie = "";

你可以这样做:

static private String sessionCookie = "";

这是超级 hacky,可能对您有用,也可能对您不起作用,具体取决于服务(和您的代码)的工作方式以及您在远程服务上可以拥有的会话数,所以我建议使用比使用更复杂的方法生产中的静态。

【讨论】:

    【解决方案2】:

    确切地说:

    SOAPHandler 类中,我们需要将会话ID 作为JSESSIONID="actual ID" 传递。以下是完整代码。

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.namespace.QName;
    import javax.xml.soap.Name;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPFactory;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPHeaderElement;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.ws.LogicalMessage;
    import javax.xml.ws.ProtocolException;
    import javax.xml.ws.handler.LogicalMessageContext;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    
    public class SOAPHandler implements
    javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {
    
    public Set<QName> getHeaders() {
    return null;
    }
    
    public void close(MessageContext mc) {
    }
    
    public boolean handleFault(SOAPMessageContext mc) {
    return true;
    }
    
    public boolean handleMessage(SOAPMessageContext mc) {
        System.out.println("Setting this before call");
    if (Boolean.TRUE.equals(mc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY))) {
       HandlerUtils.printMessageContext("Client SOAPHandler", mc);
       SOAPMessage sm = mc.getMessage();
    
    
        // Add header to outbound request (set cookie in HTTP client header)
       // Set the Cookie
       Map<String, List<String>> headers = (Map<String, List<String>>)mc.get(MessageContext.HTTP_REQUEST_HEADERS);
       if (headers == null) {
           headers = new HashMap<String, List<String>>();
           mc.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
       }
       List<String> cookie = headers.get("Cookie");
       if (cookie == null) {
           cookie = new ArrayList<String>();
           headers.put("Cookie", cookie);
       }
       cookie.add("JSESSIONID=DBE5B99503B8F4B7EF76F4959D223B3B");
    }
    
    return true;
    }
    }
    

    然后去测试服务

    public class ServiceTest {
      public static void main(String[] args) throws SFWebServiceFaultException {
    
        //Create object for service class, to get the port and call service method.
        PersonServiceImplService service = new PersonServiceImplService();
        PersonService port = service.getPersonServiceImplPort();
        SOAPHandler handler = new SOAPHandler();
    
        //Add the Handler to List
        List<Handler> handlerChain = new ArrayList<Handler>();
        handlerChain.add(handler);
    
        //Bind the handler to service 
        ((BindingProvider) port).getBinding().setHandlerChain(handlerChain);    
    
        //Call the service method
         System.out.println(port.greetPerson("Ganesh"));
      }
    }
    

    【讨论】:

    猜你喜欢
    • 2011-04-09
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多