【问题标题】:Invalid Cookie Header and then it ask's for Authorization无效的 Cookie 标头,然后它要求授权
【发布时间】:2011-07-14 03:12:46
【问题描述】:

我正在尝试抓取需要 Siteminder 身份验证的页面,因此我尝试在代码本身中传递我的用户名和密码以访问该页面并继续抓取该页面中的所有链接。这是我的Controller.java 代码。并从此 MyCrawler 类被调用。

public class Controller {
    public static void main(String[] args) throws Exception {

            CrawlController controller = new CrawlController("/data/crawl/root");

            controller.addSeed("http://ho.somehost.com/");

            controller.start(MyCrawler.class, 10);  
            controller.setPolitenessDelay(200);
            controller.setMaximumCrawlDepth(3);
    }
}

这是我的 MyCrawler.java 代码。在此,我将传递我的凭据(用户名和密码)以进行站点管理员身​​份验证。只是想确保应该在这个 MyCrawler 代码或上面的 Controller 代码中完成身份验证..???而这个爬虫代码取自这里(http://code.google.com/p/crawler4j/)

public class MyCrawler extends WebCrawler {

    Pattern filters = Pattern.compile(".*(\\.(css|js|bmp|gif|jpe?g"
            + "|png|tiff?|mid|mp2|mp3|mp4" + "|wav|avi|mov|mpeg|ram|m4v|pdf"
            + "|rm|smil|wmv|swf|wma|zip|rar|gz))$");

    public MyCrawler() {


    }

    public boolean shouldVisit(WebURL url) {

        System.out.println("RJ:- " +url);

        DefaultHttpClient client = null;

        try
        {
            // Set url
            //URI uri = new URI(url.toString());

            client = new DefaultHttpClient();

            client.getCredentialsProvider().setCredentials(
                    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, null),
                    new UsernamePasswordCredentials("test", "test"));

            // Set timeout
            //client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
            HttpGet request = new HttpGet(url.toString());

            HttpResponse response = client.execute(request);
            if(response.getStatusLine().getStatusCode() == 200)
            {
                InputStream responseIS = response.getEntity().getContent();
                BufferedReader reader = new BufferedReader(new InputStreamReader(responseIS));
                String line = reader.readLine();
                while (line != null)
                {
                    System.out.println(line);
                    line = reader.readLine();
                }
            }
            else
            {
                System.out.println("Resource not available");
            }
        }
        catch (ClientProtocolException e)
        {
            System.out.println(e.getMessage());
        }
        catch (ConnectTimeoutException e)
        {
            System.out.println(e.getMessage());
        }
        catch (IOException e)
        {
            System.out.println(e.getMessage());
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
        finally
        {
            if ( client != null )
            {
                client.getConnectionManager().shutdown();
            }
        }


        String href = url.getURL().toLowerCase();
        if (filters.matcher(href).matches()) {
            return false;
        }
        if (href.startsWith("http://")) {
            return true;
        }
        return false;
    }

    public void visit(Page page) {
        int docid = page.getWebURL().getDocid();
        String url = page.getWebURL().getURL();         
        String text = page.getText();
        List<WebURL> links = page.getURLs();
        int parentDocid = page.getWebURL().getParentDocid();

        System.out.println("Docid: " + docid);
        System.out.println("URL: " + url);
        System.out.println("Text length: " + text.length());
        System.out.println("Number of links: " + links.size());
        System.out.println("Docid of parent page: " + parentDocid);
        System.out.println("=============");
    }   
}

我正在打印 url,以便我可以看到正在打印的 url。因此,通过这种方式,它会打印两个 url,一个是需要身份验证的实际 url,然后是一些 siteminder url。当我运行这个项目时,我得到如下错误..

RJ:- http://ho.somehost.com/net/pa/ho.xhtml
 WARN [Crawler 1] Invalid cookie header: "Set-Cookie: SMCHALLENGE=; expires=Sat, 15 Jan 2011 02:52:54 GMT; path=/; domain=.somehost.com". Unable to parse expires attribute: Sat, 15 Jan 2011 02:52:54 GMT
 WARN [Crawler 1] Invalid cookie header: "Set-Co## Heading ##okie: SMIDENTITY=nzFSq2U3g/C3C6/jkj/Ocghyh/njK; expires=Sat, 13 Jul 2013 02:52:54 GMT; path=/; domain=.somehost.com". Unable to parse expires attribute: Sat, 13 Jul 2013 02:52:54 GMT
null
 INFO [Crawler 1] Number of pages fetched per second: 0
RJ:- https://lo.somehost.com/site/no/176/sm.exhtml
 WARN [Crawler 1] Invalid cookie header: "Set-Cookie: SMCHALLENGE=; expires=Sat, 15 Jan 2011 02:52:56 GMT; path=/; domain=.somehost.com". Unable to parse expires attribute: Sat, 15 Jan 2011 02:52:56 GMT
 WARN [Crawler 1] Invalid cookie header: "Set-Cookie: SMIDENTITY=IqsIPo; expires=Sat, 13 Jul 2013 02:52:56 GMT; path=/; domain=.somehost.com". Unable to parse expires attribute: Sat, 13 Jul 2013 02:52:56 GMT

任何建议都将不胜感激。如果我将该登录 url 复制粘贴到浏览器中,它会询问用户名和密码,如果我输入用户名和密码,那么我会得到实际屏幕。

【问题讨论】:

  • 不是答案,因为我没有任何方法可以重现此问题。您似乎正在使用 Apache 的 HttpComponents 项目中的 HttpClient。我建议先阅读本教程,尤其是关于身份验证 cookie 的部分;您当前的问题与不正确的 cookie 处理有关。显然,您还没有意识到或不了解 SiteMinder 身份验证的工作原理,因此我建议您阅读您必须了解的所有文档以了解它在后台是如何工作的。为什么这很重要?因为你两周来一直在问这个问题。
  • @Vineet Reynolds,感谢您的回复.. HttpClient 的相同代码在我的不同项目中运行良好,因为我发现了问题所在。如果我在这个项目中使用相同的代码,那么我会得到那个错误。所以这就是为什么我很困惑这次我做错了什么..
  • 那么,这两个项目有什么不同呢?也许这会给你一个答案。如果您已经知道,请使用该信息更新问题。
  • @Vineet Reynolds,这次只有我尝试访问的网址不同。而且用户名和密码也是一样的..
  • 好吧,我先来看看为什么 cookie 的到期日期是过去的Sat, 15 Jan 2011 02:52:54 GMT。您应该在每种情况下比较服务器的行为,从发出的 cookie 开始。当然不能排除服务器的问题。如果您需要更多帮助,我建议您进行聊天。

标签: java httpclient web-crawler


【解决方案1】:

为后代提取聊天讨论的重要内容,以防有人遇到同样的问题。

显示的警告信息,表明HttpClient 无法解析SiteMinder 发出的Set-Cookie 标头。使用 Wireshark 对网络流量的分析显示如下:

  • 没有为由 SiteMinder 发布的 cookie SMSESSION 设置过期属性。这不是问题的原因;请注意,需要查看来自负责警告的服务器的 HTTP 响应。
  • 已针对 cookie SMCHALLENGESMIDENTITY 发出警告。因此,需要检查包含这两个 cookie 的 Set-Cookie 标头的响应。
  • 问题可能出在:
    • cookie 值本身,或
    • cookie 的 expires 属性中的日期格式。
  • HttpClient 的Bug no 923 已在 HttpClient 的 4.1.1 版本中修复,并且可能包含解决方案。该修复程序同时支持 2 位和 4 位数字年份,这可能是问题的原因。

如果上述(在 cookie 过期值中使用 4 位数年份)被证明是不正确的根本原因,则必须指定用于解析 cookie 值的日期格式。这可以通过以下方式使用 HttpClient 指定允许/接受的日期格式列表来完成:

HttpGet request = new HttpGet(url.toString());
request.getParams().setParameter(CookieSpecPNames.DATE_PATTERNS, Arrays.asList("EEE, d MMM yyyy HH:mm:ss z"));
HttpResponse response = client.execute(request);

代替现有的调用:

HttpGet request = new HttpGet(url.toString());

HttpResponse response = client.execute(request);

EEE, d MMM yyyy HH:mm:ss z 指定的模式对于似乎被错误解析的日期是有效的模式(根据控制台中的消息)。如果 HttpClient 未正确处理其他日期格式,您将需要添加其他模式。有关所使用格式的详细信息,请参阅SimpleDateFormat 类文档。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-22
    • 2020-06-12
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 2019-04-23
    • 2021-12-23
    • 1970-01-01
    相关资源
    最近更新 更多