Skip to content

Commit 880b8cd

Browse files
authored
Merge pull request #7 from slipper4j/master
增加admin4j-signature文档,优化签名规则
2 parents e57948f + 8b24330 commit 880b8cd

24 files changed

Lines changed: 427 additions & 202 deletions

File tree

admin4j-common/src/main/java/com/admin4j/common/pojo/ResponseEnum.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ public enum ResponseEnum implements IResponse, Assert {
112112
ERROR_D_IDEMPOTENT(5301, "服务器内部错误 5301"),
113113

114114
REQUEST_TOO_MANY_REQUESTS(5429, "TOO_MANY_REQUESTS"),
115+
REQUEST_SIGNATURE_FAILURE(5430, "REQUEST_SIGNATURE_FAILURE"),
115116
USERNAME_NOT_FOUND(5400, "USERNAME_NOT_FOUND"),
116117
PASSWORD_ERROR(5401, "PASSWORD_ERROR"),
117118
/**

admin4j-signature/README.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# signature-spring-boot-starter
2+
`signature-spring-boot-starter` 通过注解的方式实现api接口签名
3+
4+
# 使用
5+
6+
```xml
7+
8+
<dependency>
9+
<groupId>com.admin4j.signature</groupId>
10+
<artifactId>admin4j-signature</artifactId>
11+
<version>0.8.0-SNAPSHOT</version>
12+
</dependency>
13+
```
14+
15+
## CODE
16+
17+
## 步骤1 实现SignatureApi接口
18+
```java
19+
20+
/**
21+
* 签名API实现类
22+
*/
23+
@Service
24+
public class SignatureApiImpl implements SignatureApi {
25+
26+
@Override
27+
public String getAppSecret(String appId) {
28+
// 自定义逻辑获取appSecret
29+
return "d3cbeed9baf4e68673a1f69a2445359a20022b7c28ea2933dd9db9f3a29f902b";
30+
}
31+
32+
@Override
33+
public String digestEncoder(String plainText) {
34+
// 签名加密算法,算法与前端保持一致
35+
try {
36+
return DigestUtils.md5DigestAsHex(StringUtils.getBytes(plainText, "UTF-8"));
37+
} catch (UnsupportedEncodingException e) {
38+
throw new RuntimeException(e);
39+
}
40+
}
41+
}
42+
```
43+
44+
## 步骤2 具体需要签名的地方埋点@Signature,注释中包含前端参数加签规则
45+
46+
```java
47+
@RestController
48+
@RequestMapping("/user")
49+
public class SignatureController {
50+
51+
@GetMapping("/{id}")
52+
@Signature
53+
public R get(@PathVariable("id") Long id, String name) {
54+
/**
55+
1、参与加签字段
56+
{
57+
"appId": "327189637812637",
58+
"uri": "/user/get/1",
59+
"timestamp": 1701521859352,
60+
"nonce": "1730934251223891968",
61+
"param": "{\"name\": \"张三\"}",
62+
}
63+
appId:应用ID
64+
uri:可能包含动态参数,该字段只需参与签名,无需传递;签名忽略此字段:@Signature(uri = @SignatureField(enable = false))
65+
timestamp:时间戳
66+
nonce:随机数,可以使用UUID或者雪花ID,必须10位以上,否则验签失败
67+
param:url后的请求参数,封装为一个JSON对象,key排序,最后转为JSON字符串对象
68+
69+
2、签名:
70+
sign:上面所有字段按key排序后keyvalue拼接,最后再拼接appSecret进行签名:md5("appId327189637812637nonce1730934251223891968param{"name":"张三"}timestamp1701521859352uri/user/get/1d3cbeed9baf4e68673a1f69a2445359a20022b7c28ea2933dd9db9f3a29f902b")
71+
72+
3、RequestHeader请求参数:
73+
appId=327189637812637
74+
timestamp=1701521859352
75+
nonce=1730934251223891968
76+
sign=337337309c3e799c9a13c6ad9ddbf767
77+
78+
4、RequestParam请求参数:
79+
name=张三
80+
*/
81+
User user = new User(name, id, id == 1 ? "" : "");
82+
return R.ok(user);
83+
}
84+
85+
@PostMapping
86+
@Signature
87+
public R create(@RequestBody User user) {
88+
/**
89+
1、前端加签参数, 需要按key排序
90+
{
91+
"appId": "327189637812637",
92+
"uri": "/user",
93+
"timestamp": 1701521859352,
94+
"nonce": "1730934251223891968",
95+
"body": "{"password":"1","user":{"1":"xx","2":"xx","area":"浦东新区","data":{"1":"xx","100":"xx","2":"xx","3":"xx","99":"xx"},"name":"张三","province":"上海市","sex":"男"},"username":"xiaoming"}"
96+
}
97+
appId:应用ID
98+
uri:可能包含动态参数,该字段只需参与签名,无需传递;签名忽略此字段:@Signature(uri = @SignatureField(enable = false))
99+
timestamp:时间戳
100+
nonce:随机数,可以使用UUID或者雪花ID,必须10位以上,否则验签失败
101+
body:如果body嵌套多层JSON对象或JSON数组如:{id: 1, name: "张三", "address": {"province": "上海市", "area": "浦东新区"}}
102+
那么内层对象的key也应该有顺序,需要递归处理所有JSON对象的key,最后直接把body对象转为对象字符串
103+
{
104+
"body": "{"password":"1","user":{"1":"xx","2":"xx","area":"浦东新区","data":{"1":"xx","100":"xx","2":"xx","3":"xx","99":"xx"},"name":"张三","province":"上海市","sex":"男"},"username":"xiaoming"}"
105+
}
106+
如果body是JSON数组对象,则每个JSON对象中的key同样需要有排序,同上逻辑,最后把转JSON数组为数组字符串
107+
{
108+
"body": "[{"1":"xx","2":"xx","3":"xx","area":"浦东新区","province":"上海市"},{"1":"xx","2":"xx","3":"xx","area":"徐汇区","province":"上海市"}]"
109+
}
110+
如果数组的元素非对象,则直接转为JSON字符串
111+
{
112+
"body": "["3","2","1"]"
113+
}
114+
115+
2、签名:
116+
sign:上面所有字段按key排序后keyvalue拼接,最后再拼接appSecret进行签名:md5("appIdzs001body{"password":"1","user":{"1":"xx","2":"xx","area":"浦东新区","data":{"1":"xx","100":"xx","2":"xx","3":"xx","99":"xx"},"name":"张三","province":"上海市","sex":"男"},"username":"xiaoming"}nonce1731062642266603520timestamp1701552470162uri/registerd3cbeed9baf4e68673a1f69a2445359a20022b7c28ea2933dd9db9f3a29f902b")
117+
"sign": "828a98e3c52e6c0c6a015fc99715e6e3"
118+
119+
3、RequestHeader请求参数:
120+
appId=327189637812637
121+
timestamp=1701521859352
122+
nonce=1730934251223891968
123+
sign=1b695558ae9932f1d4544ba2bc6b6c05
124+
125+
4、RequestBody请求参数:
126+
{
127+
"password": "1",
128+
"user": {
129+
"area": "浦东新区",
130+
"1": "xx",
131+
"2": "xx",
132+
"province": "上海市",
133+
"data": {
134+
"99": "xx",
135+
"1": "xx",
136+
"100": "xx",
137+
"2": "xx",
138+
"3": "xx"
139+
},
140+
"sex": "男",
141+
"name": "张三"
142+
},
143+
"username": "xiaoming"
144+
}
145+
*/
146+
return R.ok(user);
147+
}
148+
}
149+
```
150+
151+
## 重写com.admin4j.framework.signature.core.AbstractSignatureStrategy实现自定义签名规则
152+
153+

admin4j-signature/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<packaging>pom</packaging>
1616

1717
<properties>
18-
<admin4j-signature.version>0.8.0</admin4j-signature.version>
18+
<admin4j-signature.version>0.8.0-SNAPSHOT</admin4j-signature.version>
1919
<maven.compiler.source>8</maven.compiler.source>
2020
<maven.compiler.target>8</maven.compiler.target>
2121
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

admin4j-signature/signature-core/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
<groupId>org.springframework.boot</groupId>
4141
<artifactId>spring-boot-starter-data-redis</artifactId>
4242
</dependency>
43+
<!-- 工具相关 -->
44+
<dependency>
45+
<groupId>org.apache.commons</groupId>
46+
<artifactId>commons-io</artifactId>
47+
</dependency>
4348
</dependencies>
4449

4550
</project>

admin4j-signature/signature-core/src/main/java/com/admin4j/framework/signature/DefaultSignature.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)