Scrapy 2.6.2 代理设置,Proxy-Authorization 安全漏洞修复

Scrapy 2.6.2

在最新版本的 Scrapy 2.6.2 (2022-07-25) 中,更新了 Proxy-Authorization 的处理逻辑,代理的设置方式也需进行相应的更改:

官方文档:Release notes — Scrapy 2.6.2 documentation

httpproxy 源码:scrapy.downloadermiddlewares.httpproxy — Scrapy 2.6.2 documentation

根据官方描述,相关逻辑编写在 HttpProxyMiddleware 类中,源码文件在本地的路径为:

Python 安装路径\Lib\site-packages\scrapy\downloadermiddlewares\httpproxy.py,相关代码位置:

def process_request(self, request, spider):
    creds, proxy_url = None, None
    if 'proxy' in request.meta:
        if request.meta['proxy'] is not None:
            creds, proxy_url = self._get_proxy(request.meta['proxy'], '')
    elif self.proxies:
        parsed = urlparse_cached(request)
        scheme = parsed.scheme
        if (
            (
                # 'no_proxy' is only supported by http schemes
                scheme not in ('http', 'https')
                or not proxy_bypass(parsed.hostname)
            )
            and scheme in self.proxies
        ):
            creds, proxy_url = self.proxies[scheme]
​
    self._set_proxy_and_creds(request, proxy_url, creds)
    
def _set_proxy_and_creds(self, request, proxy_url, creds):
    if proxy_url:
        request.meta['proxy'] = proxy_url
    elif request.meta.get('proxy') is not None:
        request.meta['proxy'] = None
    if creds:
        request.headers[b'Proxy-Authorization'] = b'Basic ' + creds
        request.meta['_auth_proxy'] = proxy_url
    elif '_auth_proxy' in request.meta:
        if proxy_url != request.meta['_auth_proxy']:
            if b'Proxy-Authorization' in request.headers:
                del request.headers[b'Proxy-Authorization']
            del request.meta['_auth_proxy']
    elif b'Proxy-Authorization' in request.headers:
        del request.headers[b'Proxy-Authorization']

要想在保留代理的条件下删除代理凭据,需要删除 Proxy-Authorization,若一开始在请求中定义了 proxy,例如 request.meta['proxy'] = “http://username:password@some_proxy_server:port,Scrapy 会自动在请求头中设置 Proxy-Authorization,若请求头中已经设置了 Proxy-Authorization,则会导致其被删除掉,所以如果同时定义了 proxy 和 Proxy-Authorization,代码就会报错,例如:scrapy.core.downloader.handlers.http11.TunnelError: Could not open CONNECT tunnel with proxy XXXXXX:XXX [{'status': 407, 'reason': b'XXXXXXX'}]

以往在 scrapy 中设置代理的方法

1. 在 middlewares.py 中配置

方法一:

class ProxyDownloaderMiddleware:
    def process_request(self, request, spider):
        proxy = "some_proxy_server:port"
        request.meta['proxy'] = "http://%(proxy)s" % {'proxy': proxy}
        # 用户名密码认证
        request.headers['Proxy-Authorization'] = basic_auth_header('username', 'password')
        request.headers["Connection"] = "close"
        return None

方法二:

class ProxyDownloaderMiddleware:
    def process_request(self, request, spider):
        request.meta['proxy'] = "http://some_proxy_server:port"
        proxy_user_pass = "username:password"
        encoded_user_pass = base64.encodestring(proxy_user_pass)
        request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass
        request.headers["Connection"] = "close"
        return None

上述两种方法还需要在 settings.py 中进行如下配置:

DOWNLOADER_MIDDLEWARES = {
   'dltest.middlewares.ProxyDownloaderMiddleware': 100,
}
​
ROBOTSTXT_OBEY = False

2. 在 spider.py 中配置

    def start_requests(self):
        url = "代理测试网址"
        proxy = {'proxy': 'https://username:password@some_proxy_server:port'}
        yield scrapy.Request(url, callback=self.parse, meta=proxy)
​
    def parse(self, response):
        print(response.text)

Scrapy 2.6.2 中设置代理的方法

在 Scrapy 2.6.2 中前两个方法都会报错,可以改为以下方式,HttpProxyMiddleware 会自动在请求头中添加 Proxy-Authorization:

class ProxyDownloaderMiddleware:
    def process_request(self, request, spider):
        proxy = "username:password@some_proxy_server:port"
        request.meta['proxy'] = "http://%s" % proxy
        request.headers["Connection"] = "close"
        return None

跟之前一样直接在 spider.py 中配置也是可以的,还有一种方式就是将 httpproxy.py 文件中的最后两行代码注释掉也能正常运行,但是不建议使用这种方式,因为官方这么更改是为了防止代理凭据的意外泄漏,肯定是做过大量调研后决定的方案,详细安全漏洞修复说明可以阅读官方文档:

# elif b'Proxy-Authorization' in request.headers:
#    del request.headers[b'Proxy-Authorization']

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340