最近在做百度智能云的智能视联云服务
测试时候用NestJs写了下签名的生成,装包即可用
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { HmacSHA256, enc } from 'crypto-js'
import * as dayjs from 'dayjs'
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
@Injectable()
export class BaiduService {
private AK = '自己的Access Key'
private SK = '自己的Secret Key'
private host = 'evs.bj.baidubce.com'
private spaceId = '1006122'
// url 编码
UriEncodeExceptSlash(str) {
const result = encodeURIComponent(str).replace(/%2F/g, '/')
return result
}
// query-string 解析
getCanonicalQueryString(str) {
if (!str) return ''
const list = str.split('&')
if (!list.length) return ''
// 键值对编码
const keyVArr = list.map(v => {
const arr = v.split('=')
if (!arr[1]) return encodeURIComponent(v) + '='
const key = arr[0]
const value = arr[1]
return encodeURIComponent(key) + '=' + encodeURIComponent(value)
})
// 根据ASII码排序
const sortArr = keyVArr.sort((a: string, b: string) => {
let as1 = a.charCodeAt(0)
let as2 = b.charCodeAt(0)
return as1 - as2
})
// & 拼接
return sortArr.join('&')
}
getAuthorization(httpMethod = 'POST', CanonicalURI = '', CanonicalQueryString = '', x_bce_date, requestHeader) {
// 签名有效期 单位为 s
const expirationPeriodInSeconds = 1800
// 前缀字符串
const authStringPrefix = `bce-auth-v1/${this.AK}/${x_bce_date}/${expirationPeriodInSeconds}`
// 字符编码
CanonicalURI = this.UriEncodeExceptSlash(CanonicalURI)
// 字符处理
CanonicalQueryString = this.getCanonicalQueryString(CanonicalQueryString)
// 每项header编码
const headerArr: string[] = []
for (let key in requestHeader) {
const headerName = key.toLowerCase().trim()
const headerVal = encodeURIComponent(requestHeader[key].trim())
headerArr.push(headerName + ':' + headerVal)
}
const resArr = headerArr.sort((a, b) => {
// 字典序排序
return a.charCodeAt(0) - b.charCodeAt(0)
})
const CanonicalHeaders = resArr.join('\n')
// 验证请求头数组
const signedArr = resArr.map(v => {
return v.split(':')[0].trim()
})
// 认证字符串
const signedHeaders = signedArr.join(';')
const CanonicalRequest = httpMethod + "\n" + CanonicalURI + "\n" + CanonicalQueryString + "\n" + CanonicalHeaders
// 派生签名密钥
const SigningKey = enc.Hex.stringify(HmacSHA256(authStringPrefix, this.SK))
// 签名
const Signature = enc.Hex.stringify(HmacSHA256(CanonicalRequest, SigningKey)
// 认证字符串
let authorization = `bce-auth-v1/${this.AK}/${x_bce_date}/${expirationPeriodInSeconds}/${signedHeaders}/${Signature}`
return authorization
}
}
调用示例
// 获取GB28181设备通道播流链接
async getPlayUrl() {
// 调用接口的URI
let URI = `/v1/device/channel/${this.channelId}/signedUrl`
// query 参数,? 后面的内容
let query = `protocol=webrtc`
// 生成签名的时间
// @ts-ignore
const x_bce_date = dayjs().utc().format()
const requestHeader = {
'host': this.host,
'content-type': 'application/json;charset=utf-8',
'x-bce-date': x_bce_date
}
const { data: playUrl } = await axios({
method: 'GET',
url: `http://${this.host}${URI}?${query}`,
headers: {
'authorization': this.getAuthorization('GET', URI, query, x_bce_date, requestHeader),
...requestHeader,
}
})
return {
success: true,
data: playUrl,
msg: 'OK'
}
}
参考文档和工具
依赖包
crypto-js
dayjs
axios