【问题标题】:Referer missing in HTTP header of Selenium requestSelenium 请求的 HTTP 标头中缺少引用者
【发布时间】:2019-06-04 18:59:05
【问题描述】:

我正在用 Selenium 编写一些测试,并注意到标题中缺少 Referer。我编写了以下最小示例来使用https://httpbin.org/headers 进行测试:

import selenium.webdriver

options = selenium.webdriver.FirefoxOptions()
options.add_argument('--headless')

profile = selenium.webdriver.FirefoxProfile()
profile.set_preference('devtools.jsonview.enabled', False)

driver = selenium.webdriver.Firefox(firefox_options=options, firefox_profile=profile)
wait = selenium.webdriver.support.ui.WebDriverWait(driver, 10)

driver.get('http://www.python.org')
assert 'Python' in driver.title

url = 'https://httpbin.org/headers'
driver.execute_script('window.location.href = "{}";'.format(url))
wait.until(lambda driver: driver.current_url == url)
print(driver.page_source)

driver.close()

哪些打印:

<html><head><link rel="alternate stylesheet" type="text/css" href="resource://content-accessible/plaintext.css" title="Wrap Long Lines"></head><body><pre>{
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate, br", 
    "Accept-Language": "en-US,en;q=0.5", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0"
  }
}
</pre></body></html>

所以没有Referer。但是,如果我浏览到任何页面并手动执行

window.location.href = "https://httpbin.org/headers"

在 Firefox 控制台中,Referer确实按预期显示。


正如下面的 cmets 所指出的,使用时

driver.get("javascript: window.location.href = '{}'".format(url))

而不是

driver.execute_script("window.location.href = '{}';".format(url))

请求确实包含Referer。此外,当使用 Chrome 而不是 Firefox 时,两种方法都包括Referer

所以主要问题仍然存在:为什么如上所述使用 Firefox 发送请求时缺少Referer

【问题讨论】:

  • 这里的问题是 Firefox 驱动程序 / Marionette 中的错误。要获取Referer,请运行driver.get("javascript: window.location.href = 'https://httpbin.org/headers' ")
  • 这是一个错误,因为现有的默认策略不应阻止它,主要是因为它在通过控制台直接更改位置或将驱动程序切换到 Chrome 时存在。
  • 不,如果它是由 gecko 驱动程序定义的策略,那么当在控制台中手动更改位置时,您将不会获得 Referer。我的猜测是 JavaScript 沙箱会以某种方式干扰。

标签: python selenium testing http-headers http-referer


【解决方案1】:

Referer 根据 MDN 文档

Referer 请求标头包含上一个网页的地址,从该地址指向当前请求的页面的链接。 Referer 标头允许服务器识别人们从哪里访问它们,并可以将这些数据用于分析、日志记录或优化缓存等。

重要提示:尽管此标头有许多无辜的用途,但它可能会对用户安全和隐私产生不良后果。

来源:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer


但是:

如果出现以下情况,浏览器不会发送 Referer 标头:

  • 引用资源是本地“文件”或“数据”URI。
  • 使用了不安全的 HTTP 请求,并通过安全协议 (HTTPS) 接收了引用页面。

来源:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer


隐私和安全问题

Referer HTTP 标头存在一些隐私和安全风险:

Referer 标头包含上一个网页的地址,从该网页链接到当前请求的页面,可进一步用于分析、日志记录或优化缓存。

来源:https://developer.mozilla.org/en-US/docs/Web/Security/Referer_header:_privacy_and_security_concerns#The_referrer_problem


解决安全问题

Referer 标头的角度来看,大多数安全风险可以通过以下步骤得到缓解:

  • Referrer-Policy:使用服务器上的Referrer-Policy 标头来控制通过Referer 标头发送哪些信息。同样,no-referrer 指令将完全省略 Referer 标头。
  • HTML 元素上的referrerpolicy 属性有泄漏此类信息的危险(例如&lt;img&gt;&lt;a&gt;)。例如,可以将其设置为 no-referrer 以停止发送 Referer 标头。
  • 在有泄漏此类信息的危险的 HTML 元素(例如 &lt;img&gt;&lt;a&gt;)上将 rel 属性设置为 noreferrer
  • Exit Page Redirect 技术:这是目前唯一可以毫无缺陷地工作的方法是在referer 标头中设置一个您不介意的退出页面。许多网站都实现了这种方法,包括 Google 和 Facebook。如果实施正确,它不会让推荐人数据显示私人信息,而是仅显示用户来自的网站。新的引用数据将显示为http://example.com/exit?url=http%3A%2F%2Fexample.com,而不是显示为http://example.com/user/foobar 的引用数据。该方法的工作方式是让您网站上的所有外部链接都转到一个中间页面,然后重定向到最终页面。下面我们有一个指向网站 example.com 的链接,我们对完整的 URL 进行 URL 编码,并将其添加到退出页面的 url 参数中。

来源:


这个用例

我已经通过 GeckoDriver/Firefox 和 ChromeDriver/Chrome 组合执行了您的代码:

代码块:

driver.get('http://www.python.org')
assert 'Python' in driver.title

url = 'https://httpbin.org/headers'
driver.execute_script('window.location.href = "{}";'.format(url))
WebDriverWait(driver, 10).until(lambda driver: driver.current_url == url)
print(driver.page_source)

观察:

  • 使用 GeckoDriver/Firefox Referer: "https://www.python.org/" 标头缺少如下:

        {
          "headers": {
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
            "Accept-Encoding": "gzip, deflate, br", 
            "Accept-Language": "en-US,en;q=0.5", 
            "Host": "httpbin.org", 
            "Upgrade-Insecure-Requests": "1", 
            "User-Agent": "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0"
          }
        }
    
  • 使用 ChromeDriver/Chrome Referer: "https://www.python.org/" 标头存在如下:

        {
          "headers": {
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", 
            "Accept-Encoding": "gzip, deflate, br", 
            "Accept-Language": "en-US,en;q=0.9", 
            "Host": "httpbin.org", 
            "Referer": "https://www.python.org/", 
            "Upgrade-Insecure-Requests": "1", 
            "User-Agent": "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36"
          }
        }
    

结论:

GeckoDriver/Firefox 在处理Referer 标头时似乎存在问题。


结尾

Referrer Policy

【讨论】:

  • 根据您的结论,到达Referer 的唯一途径是通过execute_script
  • BrowserMob 代理没有得到积极维护,并且在 3 年内没有发布过。我是否可以建议 BrowserUp 代理 browserup.com/blog/… 它是 BrowserMob 代理的替代品,但增加了 HTTP/2、Brotli 支持、最高支持 Java 11(BrowserMob 仅支持 8)、现代依赖项和活跃的维护者。
  • execute_script 的当前实现根本无法添加 Referer 标头。它与从您提到的转换中检索标题无关。
  • @DebanjanB 所以现在您将结论更改为“GeckoDriver/Firefox 在处理 Referer 标头时似乎存在问题”。我的意思是,是的,但是的问题是什么?我该如何解决?是期望的行为还是错误?
猜你喜欢
  • 2015-11-08
  • 2018-02-03
  • 2022-01-19
  • 2011-05-04
  • 2017-12-19
  • 1970-01-01
  • 2012-01-06
  • 1970-01-01
相关资源
最近更新 更多