华为云、阿里云、AWS签名机制详解! AK/SK + HMAC-SHA256 签名鉴权!

今天在做机动车重点库是遇到了一个新的鉴权模式,本质上和:

  • 华为云
  • 阿里云
  • AWS

那套签名机制类似。 总体做下来感觉比较有记录意义,现在分享出来给大家做参考。

目录

一、需要做的事情

二、规则

三、示例

四、真正参与签名的数据

[body 要按 key 排序](#body 要按 key 排序)

五、最终签名原文

[六、Java 完整工具类(直接能用)](#六、Java 完整工具类(直接能用))

[Hmac 工具类](#Hmac 工具类)

七、调用示例

请求头

八、最容易踩坑的地方(你一定会遇到)

[1 body字段顺序](#1 body字段顺序)

[2 path 不是完整 URL](#2 path 不是完整 URL)

[3 POST 必须大写](#3 POST 必须大写)

[4 \n 换行问题](#4 \n 换行问题)

[5 body 不是 JSON](#5 body 不是 JSON)

[6 Content-Type](#6 Content-Type)

九、政务系统现状


一、需要做的事情

核心只有三步:

步骤 内容
1 组装签名字符串
2 用 SK 做 HmacSHA256
3 Base64 编码后放 header

二、规则

签名原文格式:

复制代码
HTTP_METHOD
PATH
AK
TIMESTAMP
BODY排序后的字段拼接

注意:

复制代码
是直接拼接
不是 JSON
不是 &
不是 urlencode

三、示例

请求:

复制代码
POST
"****/****/test"

AK:

复制代码
appkey92f6

时间戳:

复制代码
1685443083119

body:

复制代码
{
  "authType":1,
  "lend_time":"2023-05-19 23:00:00",
  "org_code":"51013",
  "org_code_all":"510",
  "pageNo":1,
  "pageSize":5,
  "start_time":"2023-05-19 00:00:00"
}

四、真正参与签名的数据

注意:

body 要按 key 排序

变成:

复制代码
authType1
lend_time2023-05-19 23:00:00
org_code51013
org_code_all510
pageNo1
pageSize5
start_time2023-05-19 00:00:00

五、最终签名原文

复制代码
POST
****/***/test
appkey92f6
1685443083119
authType1
lend_time2023-05-19 23:00:00
org_code51013
org_code_all510
pageNo1
pageSize5
start_time2023-05-19 00:00:00

注意:

文档里的 \n 是换行


六、Java 完整工具类(直接能用)

Hmac 工具类

复制代码
import com.alibaba.fastjson.JSON;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;

public class HmacSignUtil {

    /**
     * 生成签名
     */
    public static String sign(
            String method,
            String path,
            String ak,
            String sk,
            String timestamp,
            Map<String, Object> body
    ) throws Exception {

        // 1 body按key排序
        TreeMap<String, Object> sortedMap = new TreeMap<>(body);

        // 2 拼接body
        StringBuilder bodyBuilder = new StringBuilder();

        for (Map.Entry<String, Object> entry : sortedMap.entrySet()) {
            bodyBuilder.append(entry.getKey())
                    .append(entry.getValue());
        }

        // 3 拼接签名原文
        String signStr =
                method.toUpperCase() + "\n"
                        + path + "\n"
                        + ak + "\n"
                        + timestamp + "\n"
                        + bodyBuilder;

        System.out.println("签名原文:");
        System.out.println(signStr);

        // 4 HmacSHA256
        Mac mac = Mac.getInstance("HmacSHA256");

        SecretKeySpec secretKeySpec =
                new SecretKeySpec(sk.getBytes(StandardCharsets.UTF_8),
                        "HmacSHA256");

        mac.init(secretKeySpec);

        byte[] bytes =
                mac.doFinal(signStr.getBytes(StandardCharsets.UTF_8));

        // 5 Base64
        return Base64.getEncoder().encodeToString(bytes);
    }
}

七、调用示例

复制代码
Map<String, Object> body = new HashMap<>();

body.put("authType", 1);
body.put("lend_time", "2023-05-19 23:00:00");
body.put("org_code", "51013");
body.put("org_code_all", "510");
body.put("pageNo", 1);
body.put("pageSize", 5);
body.put("start_time", "2023-05-19 00:00:00");

String ak = "你的AK";
String sk = "你的SK";

String timestamp = String.valueOf(System.currentTimeMillis());

String sign = HmacSignUtil.sign(
        "POST",
        "****/****/test",
        ak,
        sk,
        timestamp,
        body
);

System.out.println(sign);

请求头

然后请求时:

复制代码
headers.add("X-BG-HMAC-SIGNATURE", sign);
headers.add("X-BG-HMAC-ALGORITHM", "HmacSHA256");
headers.add("X-BG-HMAC-ACCESS-KEY", ak);
headers.add("X-BG-DATE-TIME", timestamp);
headers.add("Accept", "*/*");

八、最容易踩坑的地方(你一定会遇到)

1 body字段顺序

必须:

复制代码
按 key 字典序排序

所以:

复制代码
TreeMap

非常关键。


2 path 不是完整 URL

错误:

复制代码
https://xx.com/***/test

正确:

复制代码
"****/****/test"

只取:

复制代码
/*** 后面的内容

3 POST 必须大写

复制代码
POST
GET

4 \n 换行问题

必须:

复制代码
"\n"

不能:

复制代码
System.lineSeparator()

5 body 不是 JSON

很多人会错写:

复制代码
JSON.toJSONString(body)

这是错的。

文档要求:

复制代码
key + value 拼接

6 Content-Type

只有:

复制代码
application/json
application/x-www-form-urlencoded

才参与 body 签名。


九、政务系统现状

鉴权 类型
HMAC 最常见
JWT 常见
OAuth2 平台类
国密 SM2/SM3/SM4 政务高频
RSA 签名 公安常见
相关推荐
承渊政道1 小时前
【贪心算法】(经典实战应用解析(二):最⻓递增⼦序列、递增的三元⼦序列、最⻓连续递增序列、买卖股票的最佳时机、买卖股票的最佳时机II)
数据结构·c++·学习·算法·leetcode·贪心算法·哈希算法
li星野1 小时前
动态规划十题通关:从爬楼梯到编辑距离(Python + C++)
c++·python·学习·算法·动态规划
栈溢出了1 小时前
GAT(Graph Attention Network)学习笔记
人工智能·深度学习·算法·机器学习
Tutankaaa1 小时前
学校知识竞赛怎么组织?从班级到年级的进阶方案
经验分享·学习·算法·职场和发展
qcx231 小时前
混合检索+重排序:当前 RAG 精度提升最成熟的工程路径
算法·ai·llm·agent·rag·agentic
洛水水1 小时前
【力扣100题】42.杨辉三角
算法·leetcode·职场和发展
東隅已逝,桑榆非晚1 小时前
深⼊理解指针(3)
c语言·数据结构·笔记·算法·排序算法
容器魔方1 小时前
云原生 Agent 托管的高效范式:Agent Harness Infra 体系化设计
云原生·容器·开源·云计算
地平线开发者1 小时前
地平线 征程 6 工具链进阶教程 征程 6E/M 工具链 QAT 精度调优
算法·自动驾驶