签名认证
签名计算方法
Authorization: UPYUN <Operator>:<Signature>
<Signature> = Base64 (HMAC-SHA1 (<Password>,
<Method>&
<URI>&
<Date>&
<Content-MD5>
))
相关参数说明:
参数 | 必选 | 说明 |
---|---|---|
Operator | 是 | 服务的操作员名称 |
Method | 是 | 请求方式,如:GET、POST、PUT、HEAD 等 |
URI | 是 | 请求路径 |
Date | 是 | 请求日期时间,GMT 格式字符串 (RFC 1123),如 Wed, 29 Oct 2014 02:26:58 GMT |
Content-MD5 | 否 | 请求体的 MD5 校验值,如果请求体为空,可以为空 |
Password | 是 | 服务的操作员密码的 MD5 值 |
注
- 非必选参数为空时,连同前面的
&
一起不参与签名计算。所有计算的 MD5 值,格式均是 32 位小写。 - HMAC-SHA1 输出的必须是原生的二进制数据。
- 签名计算的 Date 需要和请求 Header 里的 Date 保持一致
- 请求签名有效期为 30 分钟,如果签名超过有效期,需要重新生成签名。
- 回调签名有效期由用户自行确定,建议设置为 30 分钟。
- 回调签名的
Method
是POST
,URI
是用户接口的 URI,Date
和Content-MD5
是又拍云返回的Date和Content-MD5。
举例
参数信息:
// 操作员信息
Operator = operator123
Password = MD5(password123) = 482c811da5d5b4bc6d497ffa98491e38
// 参数
Method = POST
URI = /pretreatment/
Date = Wed, 09 Nov 2016 14:26:58 GMT
Content-MD5 = MD5(service=upyun-temp¬ify_url=/upyun_notify_url&source=/tmp.mp4&tasks=W3siYXZvcHRzIjoiL3MvMjQwcCg0OjMpL2FzLzEvci8zMCIsInJldHVybl9pbmZvIjp0cnVlLCJzYXZlX2FzIjoiL2EvYi5tcDQiLCJ0eXBlIjoidmlkZW8ifSx7ImF2b3B0cyI6Ii9pL0wyRXZZaTlqTG0xd05BPT0vaS9MekV2TWk4ekxtMXdOQT09Iiwic2F2ZV9hcyI6Ii9jb25jYXQvYS5tcDQiLCJ0eXBlIjoidmNvbmNhdCJ9XQ==&accept=json)
= a2d75510f7ec654cc24cfa2b5a5a8182
生成 Signature:
Signature = Base64 (HMAC-SHA1 (<Password>,
<Method>&
<URI>&
<Date>&
<Content-MD5>
))
// 内容拼接时,不用换行或空格,上面格式的换行或空格是为了方便阅读
= Base64 (HMAC-SHA1 (482c811da5d5b4bc6d497ffa98491e38,POST&/pretreatment/&Wed, 09 Nov 2016 14:26:58 GMT&a2d75510f7ec654cc24cfa2b5a5a8182))
// HMAC-SHA1 返回的原生二进制数据进行 Base64 编码
= 6KGqGX4tFwqnCdSndEmGQsR1jQU=
Authorization 签名:
Authorization: UPYUN upyun:6KGqGX4tFwqnCdSndEmGQsR1jQU=
完整的请求:
POST /pretreatment/ HTTP/1.1
Authorization: UPYUN upyun:6KGqGX4tFwqnCdSndEmGQsR1jQU=
Content-MD5: a2d75510f7ec654cc24cfa2b5a5a8182
Date: Wed, 9 Nov 2016 14:26:58 GMT
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: p0.api.upyun.com
Content-Length: 668
service=upyun-temp¬ify_url=/upyun_notify_url&source=/tmp.mp4&tasks=W3siYXZvcHRzIjoiL3MvMjQwcCg0OjMpL2FzLzEvci8zMCIsInJldHVybl9pbmZvIjp0cnVlLCJzYXZlX2FzIjoiL2EvYi5tcDQiLCJ0eXBlIjoidmlkZW8ifSx7ImF2b3B0cyI6Ii9pL0wyRXZZaTlqTG0xd05BPT0vaS9MekV2TWk4ekxtMXdOQT09Iiwic2F2ZV9hcyI6Ii9jb25jYXQvYS5tcDQiLCJ0eXBlIjoidmNvbmNhdCJ9XQ==&accept=json
代码演示
注意事项
- 本示例适用于云存储,云处理,内容识别,容器云服务。
- 使用时,根据自己的需求、配置,修改对应参数:
key
,secret
,uri
,method
,policy
,md5
。 - 本示例使用的
key
,secret
在不同服务中的含义不一样,云存储、云处理、内容识别(有存储) 中表示Operator
和Password
, 内容识别(无存储)、容器云表示各自服务提供的ClientKey
和ClientSecret
。 - 根据对应 API 文档说明,把认证信息,填入相应的
http
请求信息中。 - 使用
form API
上传时,需要用户生成policy
,本示例不提供生成policy
的使用实例。
常用语言代码示例
go 代码演示
package main
import (
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
"encoding/base64"
"fmt"
"strings"
"time"
)
var (
key = "upyun"
secret = "secret" // 对于上传,处理,跟内容识别需要MD5加密
uri = "/v1/apps/"
method = "GET"
)
func md5Str(s string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}
func makeRFC1123Date(d time.Time) string {
utc := d.UTC().Format(time.RFC1123)
return strings.Replace(utc, "UTC", "GMT", -1)
}
func base64ToStr(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}
func sign(key, secret, method, uri, date, policy, md5 string) string {
mac := hmac.New(sha1.New, []byte(secret))
elems := []string{}
for _, v := range []string{method, uri, date, policy, md5} {
if v != "" {
elems = append(elems, v)
}
}
value := strings.Join(elems, "&")
fmt.Println(value)
mac.Write([]byte(value))
signStr := base64ToStr(mac.Sum(nil))
return "UPYUN " + key + ":" + signStr
}
func main() {
date := makeRFC1123Date(time.Now())
fmt.Println(date)
fmt.Println(md5Str(secret))
// 上传,处理,内容识别有存储
fmt.Println(sign(key, md5Str(secret), method, uri, date, "", ""))
// 容器云,内容识别无存储
fmt.Println(sign(key, secret, method, uri, date, "", ""))
}
python 代码演示
# -*- coding: UTF-8 -*-
import base64
import datetime
import hashlib
import hmac
# Tip 1
# 使用时需要根据自己配置与需求提供参数 key secret uri method
key = 'upyun'
secret = 'secret'
uri = '/v1/apps/'
method = 'GET'
def httpdate_rfc1123(dt=None):
dt = dt or datetime.datetime.utcnow()
return dt.strftime('%a, %d %b %Y %H:%M:%S GMT')
def md5(value):
return hashlib.md5(value.encode()).hexdigest()
def sign(client_key, client_secret, method, uri, date, policy=None, md5=None):
# Tip 4
# MD5 信息可选
signarr = []
for v in [method, uri, date, policy, md5]:
if v != None:
signarr.append(v)
signstr = '&'.join(signarr)
signstr = base64.b64encode(
hmac.new(client_secret.encode(), signstr.encode(),
digestmod=hashlib.sha1).digest()
).decode()
return 'UPYUN %s:%s' % (client_key, signstr)
def main():
# Tip 2
# 时间需要与 http 头 Date 信息保持一致
# date = httpdate_rfc1123()
date = 'Thu, 14 Dec 2017 06:03:27 GMT'
# Tip 3
# sign 函数返回的值填入 http 头 Authorization 信息中
print date
print md5(secret)
# 上传,处理,内容识别有存储
print sign(key, md5(secret), method, uri, date)
# 内容识别无存储,容器云
print sign(key, secret, method, uri, date)
if __name__ == '__main__':
main()
js 代码演示
const crypto = require('crypto');
const date = new Date().toUTCString();
console.log(date);
const key = 'upyun';
const secret = 'secret';
const method = 'GET';
const uri = '/v1/apps/';
function sign(key, secret, method, uri, date, policy=null, md5=null) {
const elems = [];
[method, uri, date, policy, md5].forEach(item => {
if (item != null) {
elems.push(item)
}
})
let value = elems.join('&');
let auth = hmacsha1(secret, value);
return `UPYUN ${key}:${auth}`;
}
function MD5(value) {
return crypto.createHash('md5').update(value).digest('hex');
}
function hmacsha1(secret, value) {
return crypto.createHmac('sha1', secret).update(value, 'utf8').digest().toString('base64');
}
console.log(MD5('secret'));
// 上传,处理,内容识别有存储
console.log(sign(key, MD5(secret), method, uri, date));
// 内容识别无存储,容器云
console.log(sign(key, secret, method, uri, date));
java 代码演示
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import java.security.*;
import java.io.*;
public class auth {
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
public static String md5(String string) {
byte[] hash;
try {
hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 is unsupported", e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MessageDigest不支持MD5Util", e);
}
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
if ((b & 0xFF) < 0x10) hex.append("0");
hex.append(Integer.toHexString(b & 0xFF));
}
return hex.toString();
}
public static byte[] hashHmac(String data, String key)
throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
return mac.doFinal(data.getBytes());
}
public static String sign(String key, String secret, String method, String uri, String date, String policy,
String md5) throws Exception {
String value = method + "&" + uri + "&" + date;
if (policy != "") {
value = value + "&" + policy;
}
if (md5 != "") {
value = value + "&" + md5;
}
byte[] hmac = hashHmac(value, secret);
String sign = Base64.getEncoder().encodeToString(hmac);
return "UPYUN " + key + ":" + sign;
}
public static String getRfc1123Time() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return dateFormat.format(calendar.getTime());
}
public static void main(String[] args) throws Exception {
String key = "upyun";
String secret = "secret";
String method = "GET";
String uri = "/v1/apps/";
String date = getRfc1123Time();
System.out.println(date);
System.out.println(md5(secret));
// 上传,处理,内容识别有存储
System.out.println(sign(key, md5(secret), method, uri, date, "", ""));
// 内容识别无存储,容器云
System.out.println(sign(key, secret, method, uri, date, "", ""));
}
}
php 代码演示
<?php
function sign($key, $secret, $method, $uri, $date, $policy=null, $md5=null)
{
$elems = array();
foreach (array($method, $uri, $date, $policy, $md5) as $v)
{
if ($v)
{
$elems[] = $v;
}
}
$value = implode('&', $elems);
$sign = base64_encode(hash_hmac('sha1', $value, $secret, true));
return 'UPYUN ' . $key . ':' . $sign;
}
function main()
{
$key = 'upyun';
$secret = 'secret';
$uri = '/v1/apps/';
$method = 'GET';
$date = gmdate('D, d M Y H:i:s \G\M\T');
$md = md5($secret);
echo $md . "\n";
echo $date . "\n";
// 上传,处理,内容识别有存储
echo sign($key, md5($secret), $method, $uri, $date) . "\n";
// 内容识别无存储,容器云
echo sign($key, $secret, $method, $uri, $date);
}
main();
如有疑问请 联系我们