华为云、阿里云、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 签名 公安常见
相关推荐
Navigator_Z1 天前
LeetCode //C - 1089. Duplicate Zeros
c语言·算法·leetcode
xingyuzhisuan1 天前
自建聚合网关VS第三方聚合平台,适配场景与数据实测
人工智能·ai·云计算·oneapi
云泽8081 天前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法
万能的知了1 天前
服务器托管 vs 云主机 vs 裸金属:一个决策故事
运维·服务器·云计算
wlsh151 天前
Go 迭代器
算法
语戚1 天前
力扣 3161. 块放置查询:线段树解法(Java 实现)
java·算法·leetcode·面试·线段树·力扣·
溜达的大象1 天前
从到处找资源到统一检索:飞牛NAS部署Pansou实战记录
网络·云计算
CS创新实验室1 天前
从顺序表到动态数组:数据结构的永恒基石与现代语言的优雅封装
数据结构·算法
Black蜡笔小新1 天前
自动化AI算法训练服务器DLTM训推一体化平台助力农业生产管理实现安全智能化
人工智能·算法·自动化
8Qi81 天前
LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)
数据结构·算法·leetcode·链表·