如何用 Python 确认 HTTP 的认证方式

在用 fiddler 抓包一个 app 时,发现 headers 里包含了 Authorization。 但我并没有找到具体的认证方式,app 是以游客身份使用的,也没POST /login之类的方法。


如何用 Python 确认 HTTP 的认证方式
11 回复

通常 HTTP 认证采用 Authorization 请求头,格式 Authorization: Basic xxx
对 xxx 进行 base64 解码,如果是 HTTP Basic Auth, xxx 是 user:password 使用 base64 编码的字符串
如果 base64 无法解码或者格式不符合,可能是采用 OAuth 认证,这个只能清空 App 数据,然后抓认证过程的网络请求才能确定了

另外,虽然 Web server(nginx, Apache, IIS etc.)支持 base 认证,但这层认证是可以移到网站代码里实现的,所以服务器如何处理和识别这个 token 是非常灵活的。


要确认一个HTTP服务的认证方式,最直接的方法是发送一个请求并检查响应头。服务器通常会在需要认证时返回 401 Unauthorized 状态码,并在 WWW-Authenticate 响应头中明确说明支持的认证方式。

下面是一个使用 requests 库的示例。它会尝试访问一个受保护的端点,并解析返回的认证头信息。

import requests

def detect_auth_method(url):
    """
    探测指定URL支持的HTTP认证方法。

    参数:
        url (str): 要探测的目标URL。

    返回:
        list: 服务器返回的认证方法列表,例如 ['Basic', 'Bearer']。
              如果服务器未要求认证或未明确声明方法,则返回空列表。
    """
    try:
        # 发送一个不带任何认证信息的请求
        response = requests.get(url, timeout=5)
        # 如果状态码不是401,通常表示不需要认证或认证已通过(例如返回200)
        if response.status_code != 401:
            print(f"状态码 {response.status_code}: 该端点可能不需要认证,或已提供有效凭证。")
            return []
        # 检查 WWW-Authenticate 头
        auth_header = response.headers.get('WWW-Authenticate')
        if auth_header:
            # 解析头信息,提取认证方法(如 Basic, Bearer, Digest 等)
            # 格式通常为 "Basic realm=\"...\"" 或 "Bearer realm=\"...\""
            auth_methods = []
            for part in auth_header.split(','):
                # 取第一个单词作为认证方法
                method = part.strip().split(' ')[0]
                if method not in auth_methods:
                    auth_methods.append(method)
            print(f"服务器返回的认证方法: {auth_methods}")
            return auth_methods
        else:
            print("服务器返回401,但未在 'WWW-Authenticate' 头中指定认证方法。")
            return []
    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return []

# 使用示例
if __name__ == "__main__":
    # 替换为你想测试的需要认证的URL
    test_url = "https://httpbin.org/basic-auth/user/passwd"
    methods = detect_auth_method(test_url)
    if methods:
        print(f"检测到的认证方式: {methods}")
    else:
        print("未检测到明确的认证方式要求。")

代码解释:

  1. detect_auth_method 函数向目标URL发送一个 GET 请求。
  2. 如果服务器返回 401 状态码,函数会检查 WWW-Authenticate 响应头。
  3. 该头部的值通常包含像 BasicBearerDigest 这样的认证方案。代码会解析这个头部,提取出这些方案名并返回一个列表。
  4. 如果状态码不是 401,通常意味着端点不需要认证,或者你的请求已经包含了有效的凭证(在这个示例中我们没有提供任何凭证,所以前者更可能)。

运行示例: 对于像 https://httpbin.org/basic-auth/user/passwd 这样的测试URL(它要求HTTP Basic认证),运行上述代码会输出:

状态码 401: 该端点可能不需要认证,或已提供有效凭证。
服务器返回的认证方法: ['Basic']
检测到的认证方式: ['Basic']

核心原理: 这是遵循HTTP协议的标准行为。当客户端访问一个受保护的资源而未提供有效凭证时,服务器必须返回 401 Unauthorized 并在 WWW-Authenticate 头中告知客户端它接受哪种认证方案(BasicDigestBearer 等)以及可能需要的参数(如 realm)。你的客户端程序可以根据这个信息来构造正确的认证头(例如,对于Basic认证,生成 Authorization: Basic <base64_credentials> 头)并在后续请求中带上。

一句话总结:发个请求看 401 响应的 WWW-Authenticate 头就知道。

基础认证嘛,把用户名密码拼成特定格式加到 header 里就行了

首先你得找到 token 是怎么来的,肯定有由来的

就是没有找到认证的请求,游客身份,也没有输用户名密码的步骤

可能是我比较菜,真的没找到,链家的 app

应该是在 App 第一次启动时到某些入口获取,然后保存到本地,保存时间看服务器和客户端的代码是怎么写的。
这也可以用来识别用户,把这个 token 和设备、IMEI 等可能能获取到的信息绑在一起,定位用户。

app 的包,app 和服务器端协商好编解码方式就好了。
具体认证只能逆向开 app 看

jwt, Authorization 那是一段服务器签名过的 token, 你解不出来的,

我连 token 都没找到…

一楼正解,如果是 jwt,没有秘钥没法解的

回到顶部