鉴权-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 decode
Java1import 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}