Java 在servlet中使用httpclient 4.1作为代理

Java 在servlet中使用httpclient 4.1作为代理,java,servlets,cookies,proxy,Java,Servlets,Cookies,Proxy,我们正在编写一个J2EEJavaservlet,它作为浏览器客户端和另一台服务器之间的代理。我们在servlet中使用httpclient 4.1代码,充当浏览器请求和其他服务器调用之间的代理。这是问题的主要部分,httpclient 4.1将返回在下一组请求中使用的cookie,但它不会返回cookie,因为它们是从服务器返回的。是否可以从httpclient内的服务器获取“真实的”“设置cookie”头信息 例如(这里是将在servlet级别设置的代码的伪代码): Cookie列表是(我相信

我们正在编写一个J2EEJavaservlet,它作为浏览器客户端和另一台服务器之间的代理。我们在servlet中使用httpclient 4.1代码,充当浏览器请求和其他服务器调用之间的代理。这是问题的主要部分,httpclient 4.1将返回在下一组请求中使用的cookie,但它不会返回cookie,因为它们是从服务器返回的。是否可以从httpclient内的服务器获取“真实的”“设置cookie”头信息

例如(这里是将在servlet级别设置的代码的伪代码):

Cookie列表是(我相信)下一组请求所需的Cookie,但不是来自服务器的Cookie的精确表示

例如,如果服务器响应为:

设置Cookie:myval=

在getCookies的列表中,该列表为空。因为我们试图创建一个代理调用,我们不希望列表为空,我们可以发送myval=;从servlet返回到浏览器客户端

当httpclient处理响应时,是否可以注入某种侦听器?或者httpclient是否对所有返回的“set cookie”值都有api调用?此外,当连接到服务器时,我们可能会遇到重定向,我们还希望收集那里的所有设置cookie调用


编辑:基本上是在使用httpclient向另一台服务器发出请求时,对httpclient的调用包括重定向。是否可以沿重定向路径收集cookie信息。

由于cookie是通过使用标头设置的,因此您可以直接从响应中提取标头并转发它们:

示例使用,因为它设置了一组cookie,而不考虑用户代理:

HttpGet get = new HttpGet("http://bing.com");
final HttpResponse response = client.execute(get);
for(Header header: response.getHeaders("set-cookie")) {
    System.out.printf("%s: %s%n", header.getName(), header.getValue());
}
输出:

Set-Cookie: _FS=NU=1; domain=.bing.com; path=/
Set-Cookie: _HOP=; domain=.bing.com; path=/
Set-Cookie: _SS=SID=0E33DFF1E74942258D088E964991329D; domain=.bing.com; path=/
Set-Cookie: SRCHD=AF=NOFORM; expires=Fri, 11-Aug-2017 07:53:36 GMT; domain=.bing.com; path=/
Set-Cookie: SRCHUID=V=2&GUID=F9F751F2254D41AEBA076AF7737236E3; expires=Fri, 11-Aug-2017 07:53:36 GMT; path=/
Set-Cookie: SRCHUSR=AUTOREDIR=0&GEOVAR=&DOB=20150812; expires=Fri, 11-Aug-2017 07:53:36 GMT; domain=.bing.com; path=/
Set-Cookie: _EDGE_S=F=1&SID=1F7F788103616B0C246A708002856ABD; path=/; httponly; domain=bing.com
Set-Cookie: _EDGE_V=1; path=/; httponly; expires=Fri, 11-Aug-2017 07:53:36 GMT; domain=bing.com
Set-Cookie: MUID=3702A96D37A16DAA320AA16C36456C90; path=/; expires=Fri, 11-Aug-2017 07:53:36 GMT; domain=bing.com
Set-Cookie: MUIDB=3702A96D37A16DAA320AA16C36456C90; path=/; httponly; expires=Fri, 11-Aug-2017 07:53:36 GMT
此外,由于您是作为代理运行的,因此完全禁用cookie管理可能是一个好主意,这样您就不会使用来自不同客户端的cookie污染请求:

client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES);
更新

下面是一个示例重定向策略,该策略将所有遇到的set-cookie头存储在HttpContext中-HttpContext对于所有重定向都是相同的,但在调用execute时不同-然后在最终响应中恢复所有重定向:

public class CookieTrackingRedirectStrategy extends DefaultRedirectStrategy {

    @Override
    public boolean isRedirected(final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException {
        boolean isRedirected = super.isRedirected(request, response, context);
        List<String> allCookies = (List<String>) context.getAttribute("all-cookies");
        if(isRedirected) {
            // Store cookies from this response for future restoration
            if(allCookies == null) {
                allCookies = new ArrayList<>();
                context.setAttribute("all-cookies", allCookies);
            }
            Header[] cookies = response.getHeaders("set-cookie");
            for(Header cookie : cookies) {
                allCookies.add(cookie.getValue());
            }
        } else if(allCookies != null) {
            // Restore all cookies to this response
            for(String cookie : allCookies) {
                response.addHeader("set-cookie", cookie);
            }
        }
        return isRedirected;
    }
}
公共类CookieTrackingRedirectStrategy扩展了DefaultRedirectStrategy{
@凌驾
公共布尔值IsRedected(最终HttpRequest请求、最终HttpResponse响应、最终HttpContext上下文)抛出ProtocolException{
布尔值isRedirected=super.isRedirected(请求、响应、上下文);
List allCookies=(List)context.getAttribute(“所有cookies”);
如果(isDirected){
//存储此响应中的Cookie以备将来恢复
if(allCookies==null){
allCookies=newarraylist();
setAttribute(“所有cookies”,所有cookies);
}
Header[]cookies=response.getHeaders(“设置cookie”);
用于(标题cookie:cookies){
添加(cookie.getValue());
}
}else if(allCookies!=null){
//将所有cookie还原到此响应
for(字符串cookie:allCookies){
addHeader(“设置cookie”,cookie);
}
}
指示返回;
}
}

使用DefaultHttpClient.setRedirectStrategy设置它。

问题,为什么不使用servlet重定向请求并检索cookie?它实际上与应用程序用例有关,其中涉及向内部REST服务发出请求。servlet httpclient代码之间连接的服务器在internet上不可用。浏览器不可用。为什么不能使用RequestDispatcher重定向请求?我这样问是因为我们有一个类似的用例,我们需要从传入的请求中读取cookie,然后将其重定向到不同的servlet。请求调度器如何连接到具有不同主机名的其他服务器?Httpclient在这种情况下运行良好,问题是关于Httpclient的。不是servlet/j2ee部分。CloseableHttpResponse中的
getHeader
getAllHeader
方法如何?我正在使用HttpClient 4.4.1,这很好,但不会收集所有带有重定向的cookie。如果有10个重定向,您可能会根据最后一个服务器请求/响应打印出0个cookie。您可以禁用自动重定向处理并自己处理这些cookie以获取所有cookie头,也可以对DefaultRedirectStrategy进行子类化以拦截响应并在处理重定向之前收集cookie。我添加了一个示例RedirectStrategy它使用HttpContext跟踪所有cookie。
public class CookieTrackingRedirectStrategy extends DefaultRedirectStrategy {

    @Override
    public boolean isRedirected(final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException {
        boolean isRedirected = super.isRedirected(request, response, context);
        List<String> allCookies = (List<String>) context.getAttribute("all-cookies");
        if(isRedirected) {
            // Store cookies from this response for future restoration
            if(allCookies == null) {
                allCookies = new ArrayList<>();
                context.setAttribute("all-cookies", allCookies);
            }
            Header[] cookies = response.getHeaders("set-cookie");
            for(Header cookie : cookies) {
                allCookies.add(cookie.getValue());
            }
        } else if(allCookies != null) {
            // Restore all cookies to this response
            for(String cookie : allCookies) {
                response.addHeader("set-cookie", cookie);
            }
        }
        return isRedirected;
    }
}