背景
- 要用天翼云接口,发送get请求及鉴权对参数要求是RFC 3986编码 www.ctyun.cn/document/10…
操作
- www.npmjs.com/package/qs
- query的值编码
创建axios实例时增加一个配置属性
paramsSerializer(params) {
return qs.stringify(params, { format: 'RFC3986', encodeValuesOnly: true });
},
- 整体方案
---------- commonjs -----------------------
import RandExp from 'randexp'
import CryptoJS from 'crypto-js/crypto-js'
//客户端唯一id
export const uniqueId = () => RandExp.randexp(/[\da-z]{8}-[\da-z]{4}-[\da-z]{4}-[\da-z]{4}-[\da-z]{12}/)
export function sha256Hex(data) {
return CryptoJS.SHA256(data);
}
export function hmacsha256(val, key) {
return CryptoJS.HmacSHA256(val, key).toString();
}
export function getEopDate() {
const now = new Date(new Date().getTime() + 480 * 60000);
const ret = now.toISOString();//东八区
return ret.substring(0, ret.indexOf(".")).replaceAll("-", "").replaceAll(":", "") + "Z";
}
----------- 创建实例 ---------------
let request = axios.create({
// baseURL: "https://ecpc-global.ctapi.ctyun.cn",
timeout: TIME_OUT,
paramsSerializer(params) {
return qs.stringify(params, { format: 'RFC3986', encodeValuesOnly: true });
}
})
request.interceptors.request.use((config)=>{
let id = uniqueId()
let date = getEopDate()
const KEY_REQ_ID = "ctyun-eop-request-id";
const KEY_EOP_DATE = "eop-date";
const KEY_EOP_AUTH = "Eop-Authorization";
const ak = '0deagf44fsdfasdqed44df4dfasdfsdddd'
const sk = 'gfhavcfsdhl41f52sdfsdf1a53f4sdffff'
// ****signature****************
const sigHeader = `${KEY_REQ_ID}:${id}\n${KEY_EOP_DATE}:${date}\n`
let params = ''
if (config.params) {
// 尽管paramsSerializer会使query 里的字符转义,这儿的params的值还是原始值
params = qs.stringify(config.params, { format: 'RFC3986', encodeValuesOnly: true });
params = params.split("&").sort().join("&")
}
const body = JSON.stringify(config.data) ?? ''
// sha256Hex('') 是有值的
const sigture = `${sigHeader}\n${params}\n${sha256Hex(body)}`
// ***********kdate**********
const ktime = hmacsha256(date, sk)
const kAk = hmacsha256(ak, CryptoJS.enc.Hex.parse(ktime))
const kdate = hmacsha256(date.split('T')[0], CryptoJS.enc.Hex.parse(kAk))
// *********signature*****************
const Signature = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(hmacsha256(sigture, CryptoJS.enc.Hex.parse(kdate))));
config.headers[KEY_REQ_ID] = id
config.headers[KEY_EOP_DATE] = date
config.headers[KEY_EOP_AUTH] = `${ak} Headers=ctyun-eop-request-id;eop-date Signature=${Signature}`
return config
})
区别(网上找的)
- 误区:使用axios时若未对参数进行处理,则它的转义并不是encodeURIComponent
x-www-form-urlencoded编码规则如下:
- 将key和value用=连接起来。
- 每个键值对之间用&符号连接。
- 对每个键值对中的
值
进行编码,调用encodeURIComponent()函数实现。此函数编码除字母、数字、-、_、.、!、~、*、'、(、)外的字符,同时将空格编码为%20。 - ajax的post请求 传 qs.stringify(param),会自动设置 content-type