如何利用OAuth Consumer Key与Secret完成需登录的API任务?
问题描述
- 可完成无需登录的网页任务,但无法执行需登录的操作。
- 持有以下OAuth密钥:
"oauthConsumerKey": "example-asas-xxxx-asss-qwqweqweqweqwe" "oauthConsumerSecret": "aaaaaaaa-22ce-479e-83c4-yyyyyyyyy" - API文档提供的加载文件curl示例:
curl -X POST "https://api.example.stack.com/load/v1/load_file?clientCode=12345678&idCompany=11111111&idProcedure=11111111&fileType=File&numberOfBytes=90" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=@file.xml;type=text/xml" - 尝试复制浏览器开发者工具捕获的登录请求curl到终端执行,未成功:
curl 'https://api.example.stack.com/test/v1/code?oauth_consumer_key=example-asas-xxxx-asss-qwqweqweqweqwe&oauth_nonce=493179345&oauth_timestamp=1664784822&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=xdlTTcThh46FuTqftVYjS%2F8tIFk%3D' \ -H 'authority: api.example.stack.com' \ -H 'accept: application/json, text/plain, */*' \ -H 'accept-language: es-ES,es;q=0.9' \ -H 'cookie: _ga=GA1.3.1133377053.1663598880; JSESSIONID=C-rHN7BIjuJl2FrBWqqAulpLgcSJUvibUYvra6dq.mlasl' \ -H 'referer: https://api.example.stack.com/loader/' \ -H 'sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"' \ -H 'sec-ch-ua-mobile: ?0' \ -H 'sec-ch-ua-platform: "Linux"' \ -H 'sec-fetch-dest: empty' \ -H 'sec-fetch-mode: cors' \ -H 'sec-fetch-site: same-origin' \ -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36' \ --compressed - 知晓使用.pem证书更简便,但希望仅通过上述两个OAuth密钥完成需登录的任务。
解决方案
1. 明确失败核心原因
你复制的curl请求中,oauth_nonce(随机串)和oauth_timestamp(时间戳)是一次性有效参数,对应的oauth_signature是基于这两个值+密钥生成的专属签名,直接复用旧请求必然失效。必须针对每次请求重新生成参数并计算合法签名。
2. 手动构建合法OAuth 1.0请求
放弃复用浏览器旧curl,按照OAuth 1.0规范重新构造请求:
- 生成临时参数
oauth_nonce:用openssl rand -hex 10生成随机字符串oauth_timestamp:用date +%s获取当前Unix时间戳
- 计算HMAC-SHA1签名
严格遵循OAuth 1.0签名流程:- 构造基础字符串:将请求方法(大写)、请求URL(不带查询参数)、所有参数(OAuth参数+业务参数)做URL编码后,按字典序排序拼接
- 以
oauthConsumerSecret为密钥,对基础字符串做HMAC-SHA1哈希,再Base64编码得到oauth_signature
- 组装可执行curl
替换为新生成的OAuth参数,去掉浏览器curl中冗余的cookie、sec-*等Header,示例如下:# 定义密钥与基础信息 CONSUMER_KEY="example-asas-xxxx-asss-qwqweqweqweqwe" CONSUMER_SECRET="aaaaaaaa-22ce-479e-83c4-yyyyyyyyy" API_URL="https://api.example.stack.com/test/v1/code" # 生成临时参数 NONCE=$(openssl rand -hex 10) TIMESTAMP=$(date +%s) # 构造OAuth基础字符串(需确保参数排序、编码符合规范) ENCODED_URL=$(printf "%s" "$API_URL" | jq -sRr @uri) ENCODED_KEY=$(printf "%s" "$CONSUMER_KEY" | jq -sRr @uri) ENCODED_NONCE=$(printf "%s" "$NONCE" | jq -sRr @uri) BASE_STRING="GET&$ENCODED_URL&oauth_consumer_key=$ENCODED_KEY&oauth_nonce=$ENCODED_NONCE&oauth_signature_method=HMAC-SHA1&oauth_timestamp=$TIMESTAMP&oauth_version=1.0" # 计算签名并编码 SIGNATURE=$(echo -n "$BASE_STRING" | openssl dgst -sha1 -hmac "$CONSUMER_SECRET&" -binary | base64) ENCODED_SIGNATURE=$(printf "%s" "$SIGNATURE" | jq -sRr @uri) # 发起请求 curl "$API_URL?oauth_consumer_key=$CONSUMER_KEY&oauth_nonce=$NONCE&oauth_timestamp=$TIMESTAMP&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=$ENCODED_SIGNATURE" \ -H 'accept: application/json' \ --compressed
3. 适配文件上传的POST请求
对于load_file这类POST接口,同样需要生成OAuth参数并计算签名。注意multipart/form-data类型的请求,部分API会要求将文件参数排除在签名计算外,需参考API文档的OAuth说明。示例框架:
# 生成OAuth参数(同上步骤) NONCE=$(openssl rand -hex 10) TIMESTAMP=$(date +%s) # ...计算签名... curl -X POST "https://api.example.stack.com/load/v1/load_file?clientCode=12345678&idCompany=11111111&idProcedure=11111111&fileType=File&numberOfBytes=90&oauth_consumer_key=$CONSUMER_KEY&oauth_nonce=$NONCE&oauth_timestamp=$TIMESTAMP&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=$ENCODED_SIGNATURE" \ -H "accept: application/json" \ -F "file=@file.xml;type=text/xml" \ --compressed
4. 常见问题排查
- 确认签名计算时的基础字符串严格遵循OAuth 1.0规范:参数按字典序排序、所有特殊字符URL编码、请求方法大写
- 检查API是否要求OAuth参数放在
AuthorizationHeader中,格式为Authorization: OAuth oauth_consumer_key="xxx", oauth_nonce="yyy", ... - 去掉浏览器curl中的
cookie、sec-ch-ua等非必要Header,避免干扰请求验证
内容的提问来源于stack exchange,提问作者TonioPoce
相关产品推荐
相关产品推荐

