鉴权-AK SK方式
更新时间:2024-02-02
说明
AK/SK鉴权方式是传统的签名方式之一。调用方按照一定的规则使用SK进行签名,而被调用方则使用AK和签名来验证请求的合法性。
注意:该鉴权方式,签名存放位置在Request header的Authorization字段中。
签名
生成方式
- 生成签名(sign):对拼接字符串{ak}+{sk}+{reqTime}进行SHA256算法加密,使用UTF-8编码。
- 生成Authorization校验串:对拼接串{ak}.{sign}.{reqTime}进行Base64。
举例
ak: 123456 sk: 654321 reqTime: 1706780337628
签名(sign): d4367b0684784157017ad1daa0427d5d8b168cdfd91998e1cd81356aef59e5b0(拼接串:1234566543211706780337628)
Base64串(Authorization值):MTIzNDU2LmQ0MzY3YjA2ODQ3ODQxNTcwMTdhZDFkYWEwNDI3ZDVkOGIxNjhjZGZkOTE5OThlMWNkODEzNTZhZWY1OWU1YjAuMTcwNjc4MDMzNzYyOA== (拼接串为:123456.d4367b0684784157017ad1daa0427d5d8b168cdfd91998e1cd81356aef59e5b0.1706780337628)
校验方式
签名校验逻辑如下:
- 获取请求头 Authorization 的值
- 进行 base64 decodeJava
1import java.util.Base64; 2 3byte[] decodedBytes = Base64.getDecoder().decode({Authorization}); 4String decodedString = new String(decodedBytes);
- 根据模板 {ak}.{sign}.{reqTime} 提取出 ak、sign、reqTime 三个字段
- 通过 ak 找到约定好的 sk
- 对 ak、sk、reqTime 三个字段使用如下代码进行签名得到 selfSign
- selfSign 和 sign 对比,如果一样说明请求是安全的
POM依赖
                XML
                
            
            1<dependency>
2    <groupId>commons-codec</groupId>
3    <artifactId>commons-codec</artifactId>
4    <version>1.15</version> <!-- 使用最新版本,你可以根据实际情况选择版本 -->
5</dependency>
6
7<dependency>
8    <groupId>org.apache.commons</groupId>
9    <artifactId>commons-lang3</artifactId>
10    <version>3.12.0</version> <!-- 使用最新版本,你可以根据实际情况选择版本 -->
11</dependency>实现代码(以Java示例)
                Java
                
            
            1import org.apache.commons.codec.binary.Hex;
2import org.apache.commons.lang3.StringUtils;
3
4import java.nio.charset.StandardCharsets;
5import java.security.MessageDigest;
6import java.security.NoSuchAlgorithmException;
7import java.util.Base64;
8
9public class Main {
10
11    /**
12     * 计算签名
13     */
14    public static String calSign(String appKey, String appSecret, Long reqTime) {
15        if (StringUtils.isBlank(appKey)
16                || StringUtils.isBlank(appSecret)
17                || reqTime == null) {
18            return null;
19        }
20        String sortParam = appKey + appSecret + reqTime;
21        return sha256Hex(sortParam);
22    }
23
24    /**
25     * 使用Apache的Hex工具类实现SHA256算法
26     */
27    public static String sha256Hex(String content) {
28        String val = "";
29        if (StringUtils.isBlank(content)) {
30            return val;
31        }
32        try {
33            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
34            byte[] bytes = messageDigest.digest(content.getBytes(StandardCharsets.UTF_8));
35            val = Hex.encodeHexString(bytes);
36        } catch (NoSuchAlgorithmException e) {
37            System.out.println("使用Apache的Hex工具类实现SHA256算法出现NoSuchAlgorithmException异常");
38            System.out.println(e.getMessage());
39        } catch (Exception e) {
40            System.out.println("使用Apache的Hex工具类实现SHA256算法出现异常");
41            System.out.println(e.getMessage());
42        }
43        return val;
44    }
45
46    public static Boolean checkAuthorization(String appKey, String secretKey, String authorization) {
47        byte[] decodedBytes = Base64.getDecoder().decode(authorization);
48        String decodedString = new String(decodedBytes);
49        String[] splits = decodedString.split("\\.");
50        if (splits.length != 3) {
51            return false;
52        }
53        String sign = calSign(appKey, secretKey, Long.parseLong(splits[2]));
54        return sign.equals(splits[1]);
55    }
56
57    public static void main(String[] args) {
58        System.out.println(checkAuthorization("123456", "654321", "MTIzNDU2LmQ0MzY3YjA2ODQ3ODQxNTcwMTdhZDFkYWEwNDI3ZDVkOGIxNjhjZGZkOTE5OThlMWNkODEzNTZhZWY1OWU1YjAuMTcwNjc4MDMzNzYyOA=="));
59    }
60}