小红书API签名算法是如何实现的?具体步骤和参数解析是怎样的?
本文旨在学习和研究 API 安全机制,帮助你理解签名是如何工作的。请勿将此知识用于任何未经授权的爬取、滥用或破坏小红书平台的行为。 任何自动化操作都应严格遵守小红书的《用户服务协议》和机器人协议(robots.txt),滥用 API 可能导致你的账号被封禁,并承担相应的法律责任。
小红书 API 的签名算法是其反爬虫和系统安全的核心,它确保了每一个 API 请求都经过了客户端的合法认证,防止请求被篡改,这套算法与许多国内大型互联网公司(如阿里巴巴、腾讯)的 API 签名逻辑非常相似,核心是 HMAC-SHA256 加密。
签名算法核心思想
小红书的签名机制可以概括为以下几个步骤:
- 参数准备:收集所有请求参数(包括 URL 查询参数、Body 中的 JSON 参数等),并进行排序和拼接。
- 构建待签名字符串:将排序后的参数、请求方法、请求路径等信息,按照特定格式拼接成一个长长的字符串。
- 生成签名:使用一个动态变化的密钥和 HMAC-SHA256 加密算法,对上一步的待签名字符串进行加密,生成一个十六进制的哈希值,这个值就是最终的签名。
- 附加签名:将生成的签名作为请求头(通常是
X-Secsdk-Csrf-Token)或请求参数,发送给服务器。
详细步骤分解
第 1 步:获取签名密钥
这是最关键也最困难的一步,小红书的签名密钥不是固定的,而是通过一个动态过程获取的,这个过程通常被称为“取 CSRF Token”或“取签名密钥”。
- 入口点:通常需要先访问一个特定的、非加密的 HTTP 或 HTTPS 接口,这个接口可能是登录页、某个公共资源页,或者一个专门的“取签”接口。
- :这个接口的响应体中会包含一个 JSON 对象,里面有一个关键的字段,
data.xsecjs或data.token,这个字段的值就是临时的签名密钥。 - 密钥时效性:这个密钥通常有有效期(比如几小时或一天),过期后需要重新获取。
示例:
假设你访问 https://www.xiaohongshu.com/some/path/to/get/token,服务器返回:
{
"code": 0,
"data": {
"xsecjs": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6"
},
"msg": "success"
}
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6 就是接下来一段时间内你进行签名时要用到的密钥。
第 2 步:准备和排序参数
你需要收集所有参与签名的参数,这些参数通常包括:
- URL Query 参数:
?a=1&b=2&c=3中的a,b,c。 - Body 中的 JSON 参数:如果是
POST或PUT请求,Content-Type是application/json,JSON 对象里的所有键值对都属于参数。 - 固定参数:某些请求可能要求包含固定的参数,如
app_name,platform,version等,这些通常在请求头或文档中说明。
排序规则:
- 将所有参数的键(key)进行字典序(ASCII 顺序)升序排序。
- 注意:这里的排序是区分大小写的。
B会排在a的前面。
示例:
假设你的原始参数是 c=3&b=2&a=1&d=4。
- 提取键:
['a', 'b', 'c', 'd'] - 排序后键:
['a', 'b', 'c', 'd'](已经是排好序的)
第 3 步:构建待签名字符串
将排序后的参数按照 key=value 的格式用 & 符号拼接起来。特别注意:这里的 value 必须是URL 编码后的值。
拼接格式:
<sorted_params>&<http_method>&<request_path>
<sorted_params>:上一步排序并拼接好的字符串。<http_method>:请求的 HTTP 方法,如GET,POST,必须大写。<request_path>:请求的相对路径,不包含域名和查询参数,请求https://www.xiaohongshu.com/api/some/path?a=1,那么路径就是/api/some/path。
示例:
- 排序后的参数:
a=1&b=2&c=3&d=4 - HTTP 方法:
POST - 请求路径:
/api/search/notes
待签名字符串就是:
a=1&b=2&c=3&d=4&POST/api/search/notes
第 4 步:生成 HMAC-SHA256 签名
使用上一步获取的动态密钥和 HMAC-SHA256 算法对待签名字符串进行加密。
伪代码:
signature = HMAC-SHA256(key, string_to_sign)
这里的 key 就是你从第 1 步获取的 xsecjs 值。string_to_sign 就是你构建的待签名字符串。
示例:
假设密钥是 my_secret_key,待签名字符串是 a=1&b=2&c=3&d=4&POST/api/search/notes。
生成的签名会是一个二进制数据,然后你需要将其转换为小写的十六进制字符串。
第 5 步:附加签名并发送请求
将生成的十六进制签名附加到请求中,小红书 API 通常通过请求头来传递签名。
- 请求头名称:通常是
X-Secsdk-Csrf-Token。 - 请求头值:就是上一步生成的十六进制签名。
最终请求头示例:
POST /api/search/notes HTTP/1.1 Host: www.xiaohongshu.com Content-Type: application/json X-Secsdk-Csrf-Token: 5f4dcc3b5aa765d61d8327deb882cf99 (这是一个示例,非真实值) ...
Python 代码示例
下面是一个用 Python 实现的简化版签名算法。
import hashlib
import hmac
import urllib.parse
import json
def generate_xiaohongshu_signature(params, http_method, request_path, secret_key):
"""
生成小红书 API 签名
:param params: 请求参数字典,{'a': 1, 'b': 2}
:param http_method: HTTP 方法,如 'GET', 'POST' (必须大写)
:param request_path: 请求路径,如 '/api/search/notes'
:param secret_key: 从 API 获取的动态密钥
:return: 生成的签名 (小写十六进制字符串)
"""
# 1. 对参数的键进行排序
sorted_keys = sorted(params.keys())
# 2. 构建排序后的参数字符串 (key=value 并进行 URL 编码)
sorted_params_list = []
for key in sorted_keys:
# 确保值被转换为字符串,并进行 URL 编码
value = str(params[key])
encoded_value = urllib.parse.quote(value, safe='')
# 键也需要进行 URL 编码,以防万一
encoded_key = urllib.parse.quote(key, safe='')
sorted_params_list.append(f"{encoded_key}={encoded_value}")
sorted_params_str = "&".join(sorted_params_list)
# 3. 构建待签名字符串
string_to_sign = f"{sorted_params_str}&{http_method}{request_path}"
print(f"待签名字符串: {string_to_sign}")
# 4. 使用 HMAC-SHA256 生成签名
# hashlib.sha256 是哈希,hmac.new 才是 HMAC
signature = hmac.new(
secret_key.encode('utf-8'), # 密钥需要是 bytes
string_to_sign.encode('utf-8'), # 待签名字符串也需要是 bytes
hashlib.sha256
)
# 5. 返回小写的十六进制签名
return signature.hexdigest()
# --- 示例用法 ---
if __name__ == "__main__":
# 假设这是从某个接口获取到的动态密钥
SECRET_KEY = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6"
# 假设这是你的请求参数
request_params = {
"keyword": "美食",
"page": "1",
"search_id": "1234567890abcdef"
}
# 请求方法和路径
http_method = "POST"
request_path = "/api/search/notes"
# 生成签名
signature = generate_xiaohongshu_signature(
params=request_params,
http_method=http_method,
request_path=request_path,
secret_key=SECRET_KEY
)
print(f"生成的签名: {signature}")
# 在实际请求中,你需要将这个签名添加到请求头中
# headers = {
# "X-Secsdk-Csrf-Token": signature,
# "Content-Type": "application/json"
# }
# ...
总结与挑战
- 动态密钥获取:最大的挑战在于如何稳定、可靠地获取那个动态的
secret_key,这个过程可能涉及解析 HTML、JS 代码,或者调用另一个隐藏的 API,网站更新时,这个获取流程也可能会失效。 - 参数完整性:你需要准确知道哪些参数参与了签名,哪些没有,遗漏任何一个参数都会导致签名错误。
- 时效性:密钥有有效期,你的代码需要具备定时刷新密钥的能力。
- 反爬虫升级:小红书作为头部内容平台,其反爬虫体系会不断升级,今天的算法明天可能就会改变,需要持续投入精力去分析和适配。
再次强调,理解这些机制有助于提升你的技术能力,但请务必在法律和道德允许的范围内使用,对于个人学习和研究,建议选择开放 API 或数据允许的平台进行实践。
作者:99ANYc3cd6本文地址:https://www.chumoping.net/post/8944.html发布于 01-09
文章转载或复制请以超链接形式并注明出处初梦运营网
