为提高声网消息服务器和你的服务器之间的通信安全,声网使用签名机制进行身份验证。签名验证流程如下:
header
的 Agora-Signature
和 Agora-Signature-V2
字段中。Agora-Signature
或 Agora-Signature-V2
。你可以参考如下示例代码验证签名:
#!/usr/bin/env python2
# !-*- coding: utf-8 -*-
import hashlib
import hmac
# 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 request_body 是反序列化之前的 binary byte array,不是反序列化之后的 dictionary
request_body = '{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
secret = 'secret'
signature2 = hmac.new(secret, request_body, hashlib.sha256).hexdigest()
print(signature2) # de96da5acf03b0021ac3b4fa2225e7ae6f3533a30d50bb02c08ea4fa748bda24
#!/usr/bin/env python2
# !-*- coding: utf-8 -*-
import hashlib
import hmac
# 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 request_body 是反序列化之前的 binary byte array,不是反序列化之后的 dictionary
request_body = '{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
secret = 'secret'
signature = hmac.new(secret, request_body, hashlib.sha1).hexdigest()
print(signature) # 5a3bb6a6d9fad2ea9ae3fb707a14c9d7f3136df1
const crypto = require('crypto')
// 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 requestBody 是反序列化之前的 binary byte array,不是反序列化之后的 object
const requestBody = '{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
const secret = 'secret'
const signature2 = crypto.createHmac('sha256', secret).update(requestBody, 'utf8').digest('hex')
console.log(signature2) // de96da5acf03b0021ac3b4fa2225e7ae6f3533a30d50bb02c08ea4fa748bda24
const crypto = require('crypto')
// 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 requestBody 是反序列化之前的 binary byte array,不是反序列化之后的 object
const requestBody = '{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
const secret = 'secret'
const signature = crypto.createHmac('sha1', secret).update(requestBody, 'utf8').digest('hex')
console.log(signature) // 5a3bb6a6d9fad2ea9ae3fb707a14c9d7f3136df1
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HmacSha {
// 将加密后的字节数组转换成字符串
public static String bytesToHex(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() < 2) {
sb.append(0);
}
sb.append(hex);
}
return sb.toString();
}
//HMAC/SHA256 加密,返回加密后的字符串
public static String hmacSha256(String message, String secret) {
try {
SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(
"utf-8"), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(message.getBytes("utf-8"));
return bytesToHex(rawHmac);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
//拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 request_body 是反序列化之前的 binary byte array,不是反序列化之后的 object
String request_body = "{\"eventType\":10,\"noticeId\":\"4eb720f0-8da7-11e9-a43e-53f411c2761f\",\"notifyMs\":1560408533119,\"payload\":{\"a\":\"1\",\"b\":2},\"productId\":1}";
String secret = "secret";
System.out.println(hmacSha256(request_body, secret)); //de96da5acf03b0021ac3b4fa2225e7ae6f3533a30d50bb02c08ea4fa748bda24
}
}
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HmacSha {
// 将加密后的字节数组转换成字符串
public static String bytesToHex(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() < 2) {
sb.append(0);
}
sb.append(hex);
}
return sb.toString();
}
//HMAC/SHA1 加密,返回加密后的字符串
public static String hmacSha1(String message, String secret) {
try {
SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(
"utf-8"), "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(message.getBytes("utf-8"));
return bytesToHex(rawHmac);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
//拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 request_body 是反序列化之前的 binary byte array,不是反序列化之后的 object
String request_body = "{\"eventType\":10,\"noticeId\":\"4eb720f0-8da7-11e9-a43e-53f411c2761f\",\"notifyMs\":1560408533119,\"payload\":{\"a\":\"1\",\"b\":2},\"productId\":1}";
String secret = "secret";
System.out.println(hmacSha1(request_body, secret)); //5a3bb6a6d9fad2ea9ae3fb707a14c9d7f3136df1
}
}
<?php
function assertEqual($expect, $actual)
{
if ($expect != $actual) {
echo("\n assert failed");
echo("\n expect:\n " . $expect);
echo("\n actual:\n " . $actual);
echo("\n");
} else {
echo("assert ok\n");
echo("\n");
}
}
// 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 requestBody 是反序列化之前的 binary byte array,不是反序列化之后的 object
$request_body = '{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}';
$secret = 'secret';
// 请求 header 中 Agora-Signature-V2 的值
$sha256 = 'de96da5acf03b0021ac3b4fa2225e7ae6f3533a30d50bb02c08ea4fa748bda24';
$res2 = (hash_hmac('sha256', $request_body, $secret));
assertEqual($res2, $sha256);
?>
<?php
function assertEqual($expect, $actual)
{
if ($expect != $actual) {
echo("\n assert failed");
echo("\n expect:\n " . $expect);
echo("\n actual:\n " . $actual);
echo("\n");
} else {
echo("assert ok\n");
echo("\n");
}
}
// 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 requestBody 是反序列化之前的 binary byte array,不是反序列化之后的 object
$request_body = '{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}';
$secret = 'secret';
// 请求 header 中 Agora-Signature 的值
$sha1 = '5a3bb6a6d9fad2ea9ae3fb707a14c9d7f3136df1';
$res1 = (hash_hmac('sha1', $request_body, $secret));
assertEqual($res1, $sha1);
?>
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
// 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 request_body 是反序列化之前的 binary byte array,不是反序列化之后的 dictionary
request_body := `{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}`
secret := "secret"
fmt.Println(calcSignatureV2(secret, request_body)) // de96da5acf03b0021ac3b4fa2225e7ae6f3533a30d50bb02c08ea4fa748bda24
}
func calcSignatureV2(secret, payload string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(payload))
return hex.EncodeToString(mac.Sum(nil))
}
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"fmt"
)
func main() {
// 拿到消息通知的 raw request body 并对其计算签名,也就是说下面代码中的 request_body 是反序列化之前的 binary byte array,不是反序列化之后的 dictionary
request_body := `{"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}`
secret := "secret"
fmt.Println(calcSignatureV1(secret, request_body)) // 5a3bb6a6d9fad2ea9ae3fb707a14c9d7f3136df1
}
func calcSignatureV1(secret, payload string) string {
mac := hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(payload))
return hex.EncodeToString(mac.Sum(nil))
}