Token验证
Token格式
13003.T3.rQQzFFI7X9kjyiDEjbNnhRjXTKYjRPWerdwOkklmMXeMu1g85OHsZBtT3nxQtKknVwObtfmYoBTw_K661c5StQ
Token是一个长度小于255的字符串,中间用点(.)分隔成3个部分,依次是Header、Version、Payload
Header头部,值为渠道号Version版本号,当前版本号值为T3Payload负载,使用AES算法加密后Base64编码URLSafe的字符串
Payload内容定义
AES(channelId-userId-timestamp-channelUserId)
// 例如
AES(13003-24280710-1685709477-e7f779c82f804882ba18c5c38ed7cb4b)
channelId当前登录的渠道IDuserId用户IDtimestamp时间戳(秒),表示token生成时间,用于校验token时效性(比如60分钟内有效)channelUserId第三方渠道的用户ID(仅供参考,游戏内可忽略)
密文 rQQzFFI7X9kjyiDEjbNnhRjXTKYjRPWerdwOkklmMXeMu1g85OHsZBtT3nxQtKknVwObtfmYoBTw_K661c5StQ
AES解密之后
明文 13003-24280710-1685709477-e7f779c82f804882ba18c5c38ed7cb4b
AES算法说明
- AES加密模式:
ECB - AES加密模式:
PKCS5Padding - 密钥长度:
256位 - 密文编码:
Base64 URLSafe - 字符编码:
UTF-8 - AES_KEY:
联系发行技术获取,不与其他密钥相同
解密工具AES Encryption and Decryption Online Tool
Token示例
13003.T3.rQQzFFI7X9kjyiDEjbNnhRjXTKYjRPWerdwOkklmMXeMu1g85OHsZBtT3nxQtKknVwObtfmYoBTw_K661c5StQ
13108.T3.k_KWhzWMMY840voOlAH5dXd_6aERARR0F3GvQbXQd5rWPPfYv_lxmw8sxQN3OFDSCVP3qxfaBPloDbdwjKegvw
13301.T3.p98G7M7YnfCS9UxQ8vJapFEXmhXpYoPvSWK7c5wUIBOqNgBRYjUx3HTFlF5oA6aHwx7bNWa0T_CO2WSdVYztxbOIFSDm8oDp3IZn-SXmHn8
13303.T3.8befuFi8NzV9qZ9T9ATGtZxNgt4F8cPwv1XliedK0l-A0_NZR20WNatDHwhxgjzRdM78_BCdCbcK8yWe4CsqcQ
13306.T3.6rZvRXCEpXzCDXkuKkKQ2ziBVb_tYuveKWgqMIlRAYyL1DGtuBx4nlZBvmq0MHg4
13307.T3.ZyyVJtFqCtZ0dLEdUFnNtKseV8S43n2qANR_4aD_S8_V4R7Vg85JsAQDsIhERih9nDqfCM_WJBFK_8oiylN_Ew
13309.T3.ZkCLAJuGdetfcaiivsQu0Vj6gzlkmvkz3P4OLiYBFefUNE0PEXDStM6gMmaFKIT8
解密示例

代码示例
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public class TokenParser {
private static final String AES_KEY = "联系发行技术获取";
private static final String KEY_ALGORITHM = "AES";
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
/**
* 解密
*
* @param content 密文
* @param key 密钥
* @return 明文
*/
public static String decrypt(String content, String key) {
try {
if (key == null) {
System.out.println("AES key should not be null");
return null;
}
byte[] data = Base64.decodeBase64(content);
byte[] raw = key.getBytes(StandardCharsets.UTF_8);
SecretKeySpec keySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] original = cipher.doFinal(data);
return new String(original, StandardCharsets.UTF_8);
} catch (Exception e) {
System.out.println("解密异常error" + e.getMessage());
return null;
}
}
public static void main(String[] args) {
String token = "13003.T3.rQQzFFI7X9kjyiDEjbNnhRjXTKYjRPWerdwOkklmMXeMu1g85OHsZBtT3nxQtKknVwObtfmYoBTw_K661c5StQ";
String[] parts = token.split("\\.");
String header = parts[0];
System.out.println("header: " + header);
String version = parts[1];
System.out.println("version: " + version);
String payload = parts[2];
String result = decrypt(payload, AES_KEY);
if (result != null) {
//解密成功: 13003-24280710-1685709477-e7f779c82f804882ba18c5c38ed7cb4b
//解密参数对应: channelId-userId-timestamp-channelUserId
System.out.println("解密成功: " + result);
} else {
System.out.println("解密失败");
}
}
}