PhantomJS 不发送身份验证标头

Posted

技术标签:

【中文标题】PhantomJS 不发送身份验证标头【英文标题】:PhantomJS doesn't send authentication header 【发布时间】:2012-04-24 06:55:25 【问题描述】:

我正在尝试在 PhantomJS 中打开一个需要 HTTP 身份验证的网页。 我的脚本基于 loadspeed.js 示例:

var page = require('webpage').create(),
    t, address;
page.settings.userName = "user";
page.settings.password = "password";
if (phantom.args.length === 0) 
  console.log('Usage: loadspeed.js <some URL>');
  phantom.exit();
 else 
  t = Date.now();
  address = phantom.args[0];
  page.open(address, function (status) 
      if (status !== 'success') 
          console.log('FAIL to load the address');
       else 
          t = Date.now() - t;
          console.log('Loading time ' + t + ' msec');
          page.render('page.jpg');
      
      phantom.exit();
  );

我可以从渲染的 page.jpg 中看到,我每次都会收到 401。 我还使用 Wireshark 跟踪了 HTTP 会话,这表明在 GET 请求中没有向给定 URL 发送任何身份验证标头。

我在这里做错了什么?我刚刚开始使用 PhantomJS,但我整个晚上都在搜索,但没有走多远......

【问题讨论】:

什么浏览器? Chrome 19 只是不允许您通过 XHR 设置用户名和密码。这是因为他们不允许用户名:密码@ URL 的比例。针对不同网站的 HTTP 身份验证是一项棘手的工作。我想我会在下周末左右写一篇关于这个话题的博客。 不直接处理这个问题,但我想指出,从 PhantomJS 1.9.2 和 SlimerJS 0.8.4 开始,您的身份验证信息(无论是使用 page.settings 还是 page.customHeaders 完成)被发送到该页面上引用的所有 3rd 方服务器。 (例如,如果您登录的页面使用 CDN 作为其 jQuery,那么该 CDN 服务器会获取您的用户名和密码;对于广告服务器也是如此。)至少,SlimerJS 正在研究解决方案。 【参考方案1】:

PhantomJS(至少从 1.9.0 开始)有一个关于 auth 的错误:它发送没有 auth 标头的请求,然后只有在它返回 401 后才会再次执行请求,但这次使用标头。 (这适用于 GET;对于 POST,它根本不起作用。)

解决方法很简单,所以不要:

page.settings.userName = 'username';
page.settings.password = 'password';

你可以使用:

page.customHeaders='Authorization': 'Basic '+btoa('username:password');

(我刚刚在一篇博文中介绍了这一点:http://darrendev.blogspot.jp/2013/04/phantomjs-post-auth-and-timeouts.html,并从 Igor Semenko 那里了解到 PhantomJS 邮件列表中的解决方法。)

【讨论】:

我机器上的 PhantomJS 1.9.2 行为不正常。 page.settings.userNamepassword 有时有效,有时无效。这可能与缺少的 401 阶段无关,因为我一直在使用同一个远程服务器。使用 customHeader - 似乎总是有效。 这个问题太老了,我不知道我使用的是哪个 phantomJS 版本,但大概它对这个 bug 有一些变化。 我必须使用 1.9.12 的解决方法,并且不要忘记包含 btoa 模块。 @Pier-LucGendreau 我以为 btoa 是内置的?如果发生了变化,需要包含哪个模块? (PS 感谢您确认从 1.9.12 开始仍然需要它) @DarrenCook 我使用了这个模块:npmjs.org/package/btoa,但还有另一种方法不需要额外的依赖:***.com/questions/23097928/…【参考方案2】:

我认为您使用的脚本或 phantomjs 没有任何问题(至少在 v1.5 中)。

如果你试试这个脚本:

var page = require('webpage').create(),
    system = require('system'),
    t, address;

page.settings.userName = 'test';
page.settings.password = 'test';

if (system.args.length === 1) 
    console.log('Usage: loadspeed.js <some URL>');
    phantom.exit();
 else 
    t = Date.now();
    address = system.args[1];
    page.open(address, function (status) 
        if (status !== 'success') 
            console.log('FAIL to load the address');
         else 
            t = Date.now() - t;
            console.log('Page title is ' + page.evaluate(function () 
                return document.title;
            ));
            console.log('Loading time ' + t + ' msec');
        
        phantom.exit();
    );

phantomjs loadspeed.js http://browserspy.dk/password-ok.php

认证成功。

【讨论】:

以上是关于PhantomJS 不发送身份验证标头的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ionic 4 中发送带有标头的身份验证令牌?

如何在 ASP.Net 中为一组 Web 请求发送身份验证标头

通过 cookie 标头发送令牌身份验证信息是不是安全?

Alamofire 未创建身份验证标头来发送凭据

使用 HTTP Web 请求发送 HTTP 标头以进行 NTLM 身份验证

在标头php curl中发送身份验证