接口加密
加密注解 @MssSafety
开启请求验签
- 对于标注了 @MssSafety 注解的接口,(decryptRequest=true)请求参数需要进行加密。
开启响应加密
- 对于标注了 @MssSafety 注解的接口,(encryptResponse=true)请求参数需要进行加密。
使用语法
- 注解:
@MssSafety
| 参数 | 值 | 备注 |
|---|---|---|
| isRepetition | true / false | 默认:true |
| decryptRequest | true / false | 默认:false |
| encryptResponse | true / false | 默认:false |
| encryptType | AES / RAS | 默认:AES |
使用案例
- 后端 接口开启请求解密,响应加密注解
java
@MssSafety(decryptRequest = true,encryptResponse= true)
- 前端接口开启加密
请求头添加一下标识
text
headers: {
'Encrypt-Type': EncryptTypeEnum.AES
}
使用示例
前端请求报文进行加密

接口响应数据进行加密

注意事项
- 前段请求加密只支持
POST和PUT - 如果前端开启了请求加密(请求头需要添加下面代码),后端接口也要同时开始请求解密
text
headers: {
'Encrypt-Type': EncryptTypeEnum.AES
}java
@MssSafety(decryptRequest = true)- 如果后端的接口进行了加密处理,响应给前端,前端将自动识别到加密数据进行解密。
第三方接入 Demo(AES / RSA)
以下示例对应 后端接口使用 @MssSafety(decryptRequest = true) 的接口
例如 POST /v1/openapi/getGameList(RSA)与内部业务接口(AES)。
1) 获取 Token 与密钥
POST /v1/openapi/getToken(无需加签)返回:
token(后续放在请求头Authorization)appId(16位,作为 AES IV)secretKey(AES密钥,16位)publicKey(RSA 公钥,服务端使用私钥验签)
2) 通用请求头
Content-Type: application/jsonAuthorization: <token>App-Id: <appId>Encrypt-Type: AES或Encrypt-Type: RSAX-Sign: <sign>签名(也可以放在 body 中)X-Timestamp: <timestamp>时间戳(也可以放在 body 中)
当 decryptRequest = true 时,X-Sign 与 X-Timestamp 可不放在 header, 因为会从请求体 ApiSecurityParam 中读取并写入。
3) AES(JS,适用于浏览器/前端)
签名规则(必须与后端一致):
- 对
data进行参数排序(ASCII 升序) - 过滤空值
- 拼接为
key=value&...,并对 key/value 做encodeURIComponent - 使用
AES/CBC/ZeroPadding加密该字符串 - Base64 输出作为
sign
** 加签 JS Demo(crypto-js)**
typescript
import { AES, enc, mode, pad } from 'crypto-js';
const appId = '16位appId';
const secretKey = '16位secretKey';
const token = '登录接口返回的token';
const data = { pageNum: 1, pageSize: 10, userName: '' };
const paramsSort = (obj: Record<string, any>) => {
const keys = Object.keys(obj).sort();
const res: Record<string, any> = {};
keys.forEach((k) => (res[k] = obj[k]));
return res;
};
const tansParams = (params: Record<string, any>) => {
params = paramsSort(params);
let result = '';
for (const propName of Object.keys(params)) {
const value = params[propName];
const part = encodeURIComponent(propName) + '=';
if (value !== null && value !== '' && typeof value !== 'undefined') {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
const p = propName + '[' + key + ']';
result += encodeURIComponent(p) + '=' + encodeURIComponent(value[key]) + '&';
}
}
} else {
result += part + encodeURIComponent(value) + '&';
}
}
}
return result.endsWith('&') ? result.slice(0, -1) : result;
};
const dataStr = tansParams(data);
const iv = enc.Utf8.parse(appId);
const key = enc.Utf8.parse(secretKey);
const encrypted = AES.encrypt(enc.Utf8.parse(dataStr), key, {
iv,
mode: mode.CBC,
padding: pad.ZeroPadding,
});
const sign = enc.Base64.stringify(encrypted.ciphertext);
const body = {
appId,
sign,
timestamp: Date.now(),
data,
};
fetch('/v1/openapi/getGameList', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: token,
'App-Id': appId,
'Encrypt-Type': 'AES',
},
body: JSON.stringify(body),
});4) RSA(服务端请求:Java / PHP / Python / C#)
签名规则:
- 将
data转成 JSON 字符串(保持字段顺序与实际序列化一致) - 使用 公钥 做 RSA 加密(PKCS1 Padding)
- 将密文输出为 十六进制字符串 作为
sign
Java Demo(Hutool)
java
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSON;
String appId = "16位appId";
String publicKey = "获取Token接口返回的publicKey";
String token = "登录接口返回的token";
Map<String, Object> data = new HashMap<>();
data.put("pageNum", 1);
data.put("pageSize", 10);
data.put("userName", "");
String dataStr = JSON.toJSONString(data);
RSA rsa = new RSA(null, publicKey);
byte[] encrypted = rsa.encrypt(dataStr.getBytes(StandardCharsets.UTF_8), KeyType.PublicKey);
String sign = HexUtil.encodeHexStr(encrypted).toUpperCase();
Map<String, Object> body = new HashMap<>();
body.put("appId", appId);
body.put("sign", sign);
body.put("timestamp", System.currentTimeMillis());
body.put("data", dataStr);Python Demo(PyCryptodome)
python
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import binascii, json, time
app_id = "16位appId"
public_key = """-----BEGIN PUBLIC KEY-----
...your key...
-----END PUBLIC KEY-----"""
data = {"pageNum": 1, "pageSize": 10, "userName": ""}
data_str = json.dumps(data, separators=(',', ':'), ensure_ascii=False)
key = RSA.import_key(public_key)
cipher = PKCS1_v1_5.new(key)
encrypted = cipher.encrypt(data_str.encode('utf-8'))
sign = binascii.hexlify(encrypted).decode('utf-8').upper()
body = {
"appId": app_id,
"sign": sign,
"timestamp": int(time.time() * 1000),
"data": data_str
}PHP Demo(openssl)
php
<?php
$appId = "16位appId";
$publicKey = "-----BEGIN PUBLIC KEY-----\n...your key...\n-----END PUBLIC KEY-----";
$data = [
"pageNum" => 1,
"pageSize" => 10,
"userName" => ""
];
$dataStr = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$pubKey = openssl_pkey_get_public($publicKey);
openssl_public_encrypt($dataStr, $encrypted, $pubKey, OPENSSL_PKCS1_PADDING);
$sign = strtoupper(bin2hex($encrypted));
$body = [
"appId" => $appId,
"sign" => $sign,
"timestamp" => round(microtime(true) * 1000),
"data" => $dataStr
];C# Demo(RSA)
csharp
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
string appId = "16位appId";
string publicKeyPem = @"-----BEGIN PUBLIC KEY-----
...your key...
-----END PUBLIC KEY-----";
var data = new Dictionary<string, object> {
{ "pageNum", 1 },
{ "pageSize", 10 },
{ "userName", "" }
};
string dataStr = JsonConvert.SerializeObject(data);
using var rsa = RSA.Create();
rsa.ImportFromPem(publicKeyPem.ToCharArray());
byte[] encrypted = rsa.Encrypt(Encoding.UTF8.GetBytes(dataStr), RSAEncryptionPadding.Pkcs1);
string sign = BitConverter.ToString(encrypted).Replace("-", "").ToUpperInvariant();
var body = new Dictionary<string, object> {
{ "appId", appId },
{ "sign", sign },
{ "timestamp", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() },
{ "data", dataStr }
};5) 绑定到具体接口
以 GameApiController#getGameList 为例:
- 注解:
@MssSafety(decryptRequest = true, encryptType = SafetyTypeEnum.RSA) - Header:
Encrypt-Type: RSA - Body:
{appId, sign, timestamp, data}(data为 JSON 字符串)
