鉴权-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
import java.util.Base64; byte[] decodedBytes = Base64.getDecoder().decode({Authorization}); String decodedString = new String(decodedBytes);
- 根据模板 {ak}.{sign}.{reqTime} 提取出 ak、sign、reqTime 三个字段
- 通过 ak 找到约定好的 sk
- 对 ak、sk、reqTime 三个字段使用如下代码进行签名得到 selfSign
- selfSign 和 sign 对比,如果一样说明请求是安全的
POM依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version> <!-- 使用最新版本,你可以根据实际情况选择版本 -->
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version> <!-- 使用最新版本,你可以根据实际情况选择版本 -->
</dependency>
实现代码(以Java示例)
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Main {
/**
* 计算签名
*/
public static String calSign(String appKey, String appSecret, Long reqTime) {
if (StringUtils.isBlank(appKey)
|| StringUtils.isBlank(appSecret)
|| reqTime == null) {
return null;
}
String sortParam = appKey + appSecret + reqTime;
return sha256Hex(sortParam);
}
/**
* 使用Apache的Hex工具类实现SHA256算法
*/
public static String sha256Hex(String content) {
String val = "";
if (StringUtils.isBlank(content)) {
return val;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] bytes = messageDigest.digest(content.getBytes(StandardCharsets.UTF_8));
val = Hex.encodeHexString(bytes);
} catch (NoSuchAlgorithmException e) {
System.out.println("使用Apache的Hex工具类实现SHA256算法出现NoSuchAlgorithmException异常");
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println("使用Apache的Hex工具类实现SHA256算法出现异常");
System.out.println(e.getMessage());
}
return val;
}
public static Boolean checkAuthorization(String appKey, String secretKey, String authorization) {
byte[] decodedBytes = Base64.getDecoder().decode(authorization);
String decodedString = new String(decodedBytes);
String[] splits = decodedString.split("\\.");
if (splits.length != 3) {
return false;
}
String sign = calSign(appKey, secretKey, Long.parseLong(splits[2]));
return sign.equals(splits[1]);
}
public static void main(String[] args) {
System.out.println(checkAuthorization("123456", "654321", "MTIzNDU2LmQ0MzY3YjA2ODQ3ODQxNTcwMTdhZDFkYWEwNDI3ZDVkOGIxNjhjZGZkOTE5OThlMWNkODEzNTZhZWY1OWU1YjAuMTcwNjc4MDMzNzYyOA=="));
}
}