本文原创发布在华为开发者社区,更多鸿蒙场景化示例请见华为开发者联盟官网“行业实践与常见问题”专题页。
介绍
本示例介绍通过URL签名(v4)方式使用API访问阿里云OSS。
效果预览
使用说明
进入应用后,展示一个加号图标,点击图标即可选择要传输的图片,选择要传输的文件后,应用进行URL签名(v4)方式,即可使用API访问阿里云OSS。
实现思路
构造规范请求字段
- 参数说明
参数 | 说明 |
---|---|
method | 请求方法,目前Demo中签名只支持GET `PUT`两种请求 |
contentType | 请求的媒体类型,只有在PUT 请求时才需加入到签名中 |
date | 日期,ISO8601格式的日期 |
dateTime | 日期时间,ISO8601格式的日期时间 |
expires | 签名URL的有效时长,单位为秒(s)。最小值为1,最大值为 604800(即7天) |
bucketName | 存储空间名称 |
path | 阿里云OSS上文件保存的根路径 |
savePath | 阿里云OSS上文件的保存路径,包含文件名,不包含根路径字段 |
ossRegion | 阿里云OSS所在区域 |
accessKeyId | 临时接入KeyId |
securityToken | 临时安全token |
- PUT规范请求
PUT
/examplebucket/oss/path/test/test.txt
x-oss-additional-headers=host&x-oss-credential=accessKeyId%2F20240803%2Fcn-shanghai%2Foss%2Faliyun_v4_request&x-oss-date=20240803T130523Z&x-oss-expires=3600&x-oss-security-token=CAIS87WEEDddsada2F==&x-oss-signature-version=OSS4-HMAC-SHA256
content-type:text/plain
host:examplebucket.oss-cn-shanghai.aliyuncs.com
host
UNSIGNED-PAYLOAD
- GET规范请求
GET
/examplebucket/oss/path/test/test.txt
x-oss-additional-headers=host&x-oss-credential=accessKeyId%2F20240803%2Fcn-shanghai%2Foss%2Faliyun_v4_request&x-oss-date=20240803T130523Z&x-oss-expires=3600&x-oss-security-token=CAIS87WEEDddsada2F==&x-oss-signature-version=OSS4-HMAC-SHA256
host:examplebucket.oss-cn-shanghai.aliyuncs.com
host
UNSIGNED-PAYLOAD
签名计算
- 构造sha256Hex()函数,计算SHA256哈希值。
public sha256Hex(data: string): string {
let sha256 = cryptoFramework.createMd('SHA256');
sha256.updateSync({ data: new Uint8Array(buffer.from(data, 'utf-8').buffer) });
let sha256Output = sha256.digestSync();
let output = buffer.from(sha256Output.data).toString('hex')
return output;
}
- 构造函数zeroFormat(),获取当前日期和时间(ISO8601格式)。
private zeroFormat(num: number, length: number = 2): string {
let format = '';
for (let i = 0; i < (length - num.toString().length); i++) {
format += '0';
}
format += num.toString();
return format;
}
private dateTimeISO8601(): string {
let date = new Date();
let rc = this.zeroFormat(date.getFullYear(), 4) + this.zeroFormat(date.getMonth() + 1) +
this.zeroFormat(date.getDate()) + 'T' + this.zeroFormat(date.getUTCHours()) +
this.zeroFormat(date.getMinutes()) + this.zeroFormat(date.getSeconds()) + 'Z';
return rc;
}
···
- 构造canonicalRequest()函数,用以构造规范请求字符串,注意的是以下代码字符串顺序不能改变,否则与阿里云OSS上计算的签名不一致。
private canonicalRequest(method: string, date: string, dateTime: string, pathOss: string, contentType: string = ''): string {
let canonicalRequest = method + "\n";
canonicalRequest += this.canonicalURI(pathOss);
canonicalRequest += this.canonicalQueryString(date, dateTime);
if (method === 'PUT') {
canonicalRequest += "content-type:" + contentType + '\n';
}
canonicalRequest += 'host:' + this.ossInfo.bucket_name + '.' + this.ossInfo.endpoint + '\n';
canonicalRequest += '\n';
canonicalRequest += 'host\n';
canonicalRequest += 'UNSIGNED-PAYLOAD';
return canonicalRequest;
}
- 构造signString()函数,用以构造签名字符串,以下代码字符串顺序不能改变,否则与阿里云OSS上计算的签名不一致
private signString(date: string, dateTime: string, canonical: string): string {
let stringToSign = '';
stringToSign += 'OSS4-HMAC-SHA256' + '\n';
stringToSign += dateTime + '\n';
stringToSign += date + '/' + this.ossRegion() + '/oss/aliyun_v4_request' + '\n';
stringToSign += canonical;
console.log(TAG, "stringToSign: " + stringToSign);
return stringToSign;
}
- 构造calcSignature()函数,通过调用三方库CryptoJS方法去计算签名。
private calcSignature(date: string, signString: string): string {
let dateKey: Uint8Array = CryptoJS.HmacSHA256(date, "aliyun_v4" + this.ossKey.AccessKeySecret);
let regionKey: Uint8Array = CryptoJS.HmacSHA256(this.ossRegion(), dateKey);
let regionServiceKey: Uint8Array = CryptoJS.HmacSHA256("oss", regionKey);
let signingKey: Uint8Array = CryptoJS.HmacSHA256("aliyun_v4_request", regionServiceKey);
let signature: string = CryptoJS.HmacSHA256(signString, signingKey).toString();
console.log(TAG, "response: signature: " + signature);
return signature;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。