杰瑞科技汇

Python urllib2 认证如何实现?

urllib2 是 Python 2 标准库中用于打开 URL(主要是 HTTP)的模块,当访问需要用户名和密码的网站时,就需要进行身份认证。

Python urllib2 认证如何实现?-图1
(图片来源网络,侵删)

核心概念

urllib2 中,认证主要通过两个核心类来实现:

  1. urllib2.HTTPBasicAuthHandler: 处理 HTTP 基本认证,这是一种简单但不太安全的认证方式,用户名和密码经过 Base64 编码后发送给服务器,但没有加密。
  2. urllib2.HTTPDigestAuthHandler: 处理 HTTP 摘要认证,比基本认证更安全,因为它不会在网络中直接传输密码,而是传输一个“。

工作流程

使用 urllib2 进行认证的标准流程如下:

  1. 创建一个密码管理器 (HTTPPasswordMgrWithDefaultRealm):这个对象用于存储 URL、用户名和密码的映射关系。
  2. 添加凭据:将需要认证的 URL、用户名和密码添加到密码管理器中。
  3. 创建一个认证处理器 (HTTPBasicAuthHandlerHTTPDigestAuthHandler):将密码管理器与认证处理器关联起来。
  4. 创建一个opener (build_opener):使用 urllib2.build_opener() 方法,将认证处理器添加到其中,创建一个可以处理认证的“opener”。
  5. 安装opener (install_opener):可选步骤,将这个自定义的 opener 安装为全局默认的 opener,之后所有 urllib2.urlopen() 调用都会自动使用这个 opener。
  6. 打开URL:使用 urlopen() 打开需要认证的 URL,如果服务器返回 401 Unauthorized 错误,认证处理器会自动从密码管理器中查找凭据并重试请求。

示例代码

下面我们通过两个具体的例子来演示如何实现基本认证和摘要认证。

示例 1: HTTP 基本认证

假设我们要访问一个需要基本认证的网站 http://example.com/protected,用户名是 user,密码是 pass

Python urllib2 认证如何实现?-图2
(图片来源网络,侵删)
import urllib2
import base64
# --- 方法一:直接在 Request 中添加 Authorization 头 ---
def auth_method_1():
    print "--- 使用方法一 (直接添加头) ---"
    url = 'http://example.com/protected' # 替换为实际的URL
    username = 'user'
    password = 'pass'
    # 创建一个 Request 对象
    request = urllib2.Request(url)
    # 将用户名和密码拼接成 "username:password" 的格式
    base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
    # 创建 Authorization 头,格式为 "Basic base64string"
    request.add_header("Authorization", "Basic %s" % base64string)
    try:
        response = urllib2.urlopen(request)
        print "Response Code:", response.getcode()
        print "Response Body:", response.read()
    except urllib2.HTTPError as e:
        print "Error Code:", e.code
        print "Error Reason:", e.reason
    except urllib2.URLError as e:
        print "URLError:", e.reason
# --- 方法二:使用 HTTPBasicAuthHandler (推荐) ---
def auth_method_2():
    print "\n--- 使用方法二 (推荐使用 AuthHandler) ---"
    url = 'http://example.com/protected' # 替换为实际的URL
    username = 'user'
    password = 'pass'
    # 1. 创建密码管理器
    password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
    # 2. 添加凭据
    # 第一个参数是 "域" (realm),如果不知道,可以使用 None
    # 这表示这个用户名/密码可以用于任何需要认证的 URL
    password_mgr.add_password(None, url, username, password)
    # 3. 创建认证处理器
    handler = urllib2.HTTPBasicAuthHandler(password_mgr)
    # 4. 创建 opener
    opener = urllib2.build_opener(handler)
    # 5. (可选) 安装 opener 为全局默认
    # 之后所有的 urllib2.urlopen 调用都会使用这个 opener
    urllib2.install_opener(opener)
    # 6. 打开 URL
    # 如果服务器返回 401,handler 会自动使用 password_mgr 中的凭据重试
    try:
        response = urllib2.urlopen(url)
        print "Response Code:", response.getcode()
        print "Response Body:", response.read()
    except urllib2.HTTPError as e:
        print "Error Code:", e.code
        print "Error Reason:", e.reason
    except urllib2.URLError as e:
        print "URLError:", e.reason
# 运行示例
if __name__ == '__main__':
    # 注意:你需要将 'http://example.com/protected' 替换成一个真实存在的、需要认证的URL
    # auth_method_1()
    # auth_method_2()
    pass

代码解释:

  • 方法一:手动构建 Authorization 头,这种方式简单直接,但不够灵活,如果一个站点有多个需要认证的路径,你需要为每个路径都手动处理。
  • 方法二:这是 urllib2 推荐的方式。HTTPBasicAuthHandler 会自动处理 401 错误,并尝试你提供的凭据,它更加模块化和可重用。

示例 2: HTTP 摘要认证

认证的流程与基本认证类似,只是将 HTTPBasicAuthHandler 换成 HTTPDigestAuthHandler

import urllib2
def digest_auth_example():
    print "--- HTTP 摘要认证示例 ---"
    url = 'http://example.com/digest-protected' # 替换为实际的URL
    username = 'user'
    password = 'pass'
    # 1. 创建密码管理器
    password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
    # 2. 添加凭据
    password_mgr.add_password(None, url, username, password)
    # 3. 创建认证处理器 (使用 Digest 而不是 Basic)
    handler = urllib2.HTTPDigestAuthHandler(password_mgr)
    # 4. 创建 opener
    opener = urllib2.build_opener(handler)
    # 5. 打开 URL
    try:
        response = opener.open(url)
        print "Response Code:", response.getcode()
        print "Response Body:", response.read()
    except urllib2.HTTPError as e:
        print "Error Code:", e.code
        print "Error Reason:", e.reason
    except urllib2.URLError as e:
        print "URLError:", e.reason
# 运行示例
if __name__ == '__main__':
    # digest_auth_example()
    pass

处理代理认证

如果你需要通过一个需要认证的代理服务器访问互联网,过程也非常相似,只是使用 ProxyBasicAuthHandlerProxyDigestAuthHandler

import urllib2
def proxy_auth_example():
    print "--- 代理认证示例 ---"
    # 目标 URL
    url = 'http://www.example.com'
    # 代理服务器地址和端口
    proxy_url = 'http://proxy.example.com:8080'
    # 代理服务器用户名和密码
    proxy_user = 'proxy_user'
    proxy_pass = 'proxy_pass'
    # 1. 创建密码管理器
    password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
    # 2. 添加代理凭据
    # 注意 add_password 的第二个参数是代理的 URL
    password_mgr.add_password(None, proxy_url, proxy_user, proxy_pass)
    # 3. 创建代理认证处理器
    proxy_handler = urllib2.ProxyBasicAuthHandler(password_mgr)
    # 4. (可选) 创建一个普通处理器,用于处理非代理请求
    # 如果不添加,opener 可能无法直接连接目标 URL
    # opener = urllib2.build_opener(proxy_handler) # 这样可能不够
    opener = urllib2.build_opener(proxy_handler, urllib2.ProxyHandler({})) # 更稳妥
    # 5. 安装 opener
    urllib2.install_opener(opener)
    # 6. 打开目标 URL
    # 请求会先通过代理,代理认证处理器会自动处理
    try:
        response = urllib2.urlopen(url)
        print "Response Code:", response.getcode()
        print "Response Body:", response.read()
    except urllib2.HTTPError as e:
        print "Error Code:", e.code
        print "Error Reason:", e.reason
    except urllib2.URLError as e:
        print "URLError:", e.reason
# 运行示例
if __name__ == '__main__':
    # proxy_auth_example()
    pass

重要提示:Python 3 的迁移

Python 2 已经停止维护,强烈建议你迁移到 Python 3。

在 Python 3 中,urllib2 被重构并拆分到了 urllib.requesturllib.error 等模块中,认证的逻辑基本保持不变,只是模块名和导入方式变了。

Python 3 对比示例:

# Python 3 代码
import urllib.request
import urllib.error
import base64
# 基本认证 (方法二)
url = 'http://example.com/protected'
username = 'user'
password = 'pass'
# 1. 创建密码管理器
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# 2. 添加凭据
password_mgr.add_password(None, url, username, password)
# 3. 创建认证处理器
handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
# 4. 创建 opener
opener = urllib.request.build_opener(handler)
# 5. 安装 opener
# urllib.request.install_opener(opener) # 可选
# 6. 打开 URL
try:
    # 注意:在 Python 3 中,urlopen 返回的是一个 bytes 对象,需要解码
    response = opener.open(url)
    print("Response Code:", response.getcode())
    print("Response Body:", response.read().decode('utf-8'))
except urllib.error.HTTPError as e:
    print("Error Code:", e.code)
    print("Error Reason:", e.reason)
except urllib.error.URLError as e:
    print("URLError:", e.reason)
功能 Python 2 (urllib2) Python 3 (urllib.request)
基本认证处理器 HTTPBasicAuthHandler HTTPBasicAuthHandler
密码管理器 HTTPPasswordMgrWithDefaultRealm HTTPPasswordMgrWithDefaultRealm
构建 Opener build_opener() build_opener()
打开 URL urlopen() urlopen()
导入模块 import urllib2 import urllib.request

掌握 urllib2 的认证方法对于 Python 2 的开发很重要,但请务必将学习重点转向 Python 3 及其 urllib.request 模块。

分享:
扫描分享到社交APP
上一篇
下一篇