Skip to content

Commit 064a35b

Browse files
author
WeiziPlus
committed
1.0.2 新增SignValidation注解,用于拦截需要进行签名的请求
1 parent 95fe8b6 commit 064a35b

File tree

8 files changed

+227
-12
lines changed

8 files changed

+227
-12
lines changed

springboot/demo-common/src/main/java/com/weiziplus/common/util/Md5Utils.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,14 @@ public static String encode16(String str) {
3939
return encode.substring(8, 24);
4040
}
4141

42+
/**
43+
* 32位没有加密盐
44+
*
45+
* @param str
46+
* @return
47+
*/
48+
public static String encodeNotSalt(String str) {
49+
return DigestUtils.md5DigestAsHex(str.getBytes(StandardCharsets.UTF_8)).toUpperCase();
50+
}
51+
4252
}

springboot/demo-pc/src/main/java/com/weiziplus/pc/common/interceptor/AuthorizationInterceptor.java

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import com.alibaba.fastjson.JSON;
44
import com.weiziplus.common.async.LogAsync;
55
import com.weiziplus.common.async.UserAsync;
6-
import com.weiziplus.common.util.HttpRequestUtils;
7-
import com.weiziplus.common.util.ResultUtils;
8-
import com.weiziplus.common.util.ToolUtils;
9-
import com.weiziplus.common.util.UserAgentUtils;
6+
import com.weiziplus.common.util.*;
107
import com.weiziplus.common.util.redis.StringRedisUtils;
118
import com.weiziplus.common.util.token.AdminTokenUtils;
129
import com.weiziplus.common.util.token.JwtTokenUtils;
@@ -22,6 +19,7 @@
2219

2320
import javax.servlet.http.HttpServletRequest;
2421
import javax.servlet.http.HttpServletResponse;
22+
import java.io.Console;
2523
import java.lang.reflect.Method;
2624
import java.util.*;
2725

@@ -185,7 +183,12 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
185183
handleResponse(response, ResultUtils.errorToken("token不存在"));
186184
return false;
187185
}
188-
return handleAdminToken(request, response, object);
186+
//保存用户操作,校验用户权限等
187+
if (!handleAdminToken(request, response, object)) {
188+
return false;
189+
}
190+
//校验签名
191+
return handleSign(request, response, object);
189192
}
190193

191194
/**
@@ -279,6 +282,46 @@ private boolean handleAdminToken(HttpServletRequest request, HttpServletResponse
279282
return false;
280283
}
281284

285+
/**
286+
* 是否需要签名处理
287+
* 所有请求参数(排除__sign)需要按照ascii排序,然后进行MD5加密
288+
*
289+
* @param request
290+
* @param response
291+
* @param object
292+
* @return
293+
*/
294+
private boolean handleSign(HttpServletRequest request, HttpServletResponse response, Object object) {
295+
HandlerMethod handlerMethod = (HandlerMethod) object;
296+
Method method = handlerMethod.getMethod();
297+
//如果没有签名注解直接返回
298+
if (null == handlerMethod.getBeanType().getAnnotation(SignValidation.class)
299+
&& null == method.getAnnotation(SignValidation.class)) {
300+
return true;
301+
}
302+
TreeMap<String, String[]> stringTreeMap = new TreeMap<>(request.getParameterMap());
303+
Set<String> keySet = stringTreeMap.keySet();
304+
String signParam = "__sign";
305+
if (!keySet.contains(signParam)) {
306+
handleResponse(response, ResultUtils.error("签名错误"));
307+
return false;
308+
}
309+
StringBuilder stringBuilder = new StringBuilder();
310+
for (String key : keySet) {
311+
//跳过__sign参数
312+
if (signParam.equals(key)) {
313+
continue;
314+
}
315+
stringBuilder.append(key).append("=").append(stringTreeMap.get(key)[0]).append("&");
316+
}
317+
String s = Md5Utils.encodeNotSalt(stringBuilder.substring(0, stringBuilder.length() - 1));
318+
if (stringTreeMap.get(signParam)[0].equals(s)) {
319+
return true;
320+
}
321+
handleResponse(response, ResultUtils.error("签名错误"));
322+
return false;
323+
}
324+
282325
/**
283326
* 将token出错信息输入到前端页面
284327
*
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.weiziplus.pc.common.interceptor;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* 方法或类需要sign签名验证
10+
*
11+
* @author wanglongwei
12+
* @date 2020/06/04 09/17
13+
*/
14+
@Target({ElementType.METHOD, ElementType.TYPE})
15+
@Retention(RetentionPolicy.RUNTIME)
16+
public @interface SignValidation {
17+
}

springboot/demo-web/src/main/java/com/weiziplus/web/common/interceptor/AuthorizationInterceptor.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import com.alibaba.fastjson.JSON;
44
import com.weiziplus.common.async.LogAsync;
55
import com.weiziplus.common.async.UserAsync;
6-
import com.weiziplus.common.util.HttpRequestUtils;
7-
import com.weiziplus.common.util.ResultUtils;
8-
import com.weiziplus.common.util.ToolUtils;
9-
import com.weiziplus.common.util.UserAgentUtils;
6+
import com.weiziplus.common.util.*;
107
import com.weiziplus.common.util.redis.StringRedisUtils;
118
import com.weiziplus.common.util.token.JwtTokenUtils;
129
import com.weiziplus.common.util.token.WebTokenUtils;
@@ -181,7 +178,12 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
181178
handleResponse(response, ResultUtils.errorToken("token不存在"));
182179
return false;
183180
}
184-
return handleWebToken(request, response, object);
181+
//保存用户日志
182+
if (!handleWebToken(request, response, object)) {
183+
return false;
184+
}
185+
//校验签名
186+
return handleSign(request, response, object);
185187
}
186188

187189
/**
@@ -241,6 +243,45 @@ private boolean handleWebToken(HttpServletRequest request, HttpServletResponse r
241243
return true;
242244
}
243245

246+
/**
247+
* 是否需要签名处理
248+
*
249+
* @param request
250+
* @param response
251+
* @param object
252+
* @return
253+
*/
254+
private boolean handleSign(HttpServletRequest request, HttpServletResponse response, Object object) {
255+
HandlerMethod handlerMethod = (HandlerMethod) object;
256+
Method method = handlerMethod.getMethod();
257+
//如果没有签名注解直接返回
258+
if (null == handlerMethod.getBeanType().getAnnotation(SignValidation.class)
259+
&& null == method.getAnnotation(SignValidation.class)) {
260+
return true;
261+
}
262+
TreeMap<String, String[]> stringTreeMap = new TreeMap<>(request.getParameterMap());
263+
Set<String> keySet = stringTreeMap.keySet();
264+
String signParam = "__sign";
265+
if (!keySet.contains(signParam)) {
266+
handleResponse(response, ResultUtils.error("签名错误"));
267+
return false;
268+
}
269+
StringBuilder stringBuilder = new StringBuilder();
270+
for (String key : keySet) {
271+
//跳过__sign参数
272+
if (signParam.equals(key)) {
273+
continue;
274+
}
275+
stringBuilder.append(key).append("=").append(stringTreeMap.get(key)[0]).append("&");
276+
}
277+
String s = Md5Utils.encodeNotSalt(stringBuilder.substring(0, stringBuilder.length() - 1));
278+
if (stringTreeMap.get(signParam)[0].equals(s)) {
279+
return true;
280+
}
281+
handleResponse(response, ResultUtils.error("签名错误"));
282+
return false;
283+
}
284+
244285
/**
245286
* 将token出错信息输入到前端页面
246287
*
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.weiziplus.web.common.interceptor;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* 方法或类需要sign签名验证
10+
*
11+
* @author wanglongwei
12+
* @date 2020/06/04 09/17
13+
*/
14+
@Target({ElementType.METHOD, ElementType.TYPE})
15+
@Retention(RetentionPolicy.RUNTIME)
16+
public @interface SignValidation {
17+
}

vue/src/components/table/Complex.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,12 @@
613613
}
614614
615615
/*表格树形结构,箭头错位*/
616-
.el-table table tbody tr td.tree .cell.el-tooltip {
616+
.el-table table tbody tr td:nth-child(3) .cell.el-tooltip {
617+
display: flex;
618+
}
619+
620+
/*表格树形结构,箭头错位*/
621+
.el-table table tbody tr td:nth-child(2) .cell.el-tooltip {
617622
display: flex;
618623
}
619624

vue/src/utils/axios.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,30 @@ axios.interceptors.request.use(
2121
}
2222
);
2323

24+
/**
25+
* 获取url中参数的map
26+
* @param url
27+
*/
28+
function getUrlParamMap(url) {
29+
let split = url.split("?");
30+
if (1 >= split.length) {
31+
return {};
32+
}
33+
let params = split[1].split("&") || [];
34+
let obj = {};
35+
params.forEach(value => {
36+
let param = value.split('=');
37+
obj[param[0]] = param[1];
38+
});
39+
return obj;
40+
}
41+
2442
/**
2543
* 封装axios请求
2644
*
2745
* @param allUrl 请求的url为完整url
2846
* @param allSuccess 返回所有成功回调,不包含status不是200的出错请求
47+
* @param isSign 是否需要计算签名
2948
* @param url 请求地址
3049
* @param method 请求方式
3150
* @param headers 请求头
@@ -41,6 +60,7 @@ export function weiAxios(
4160
{
4261
allUrl = false,
4362
allSuccess = false,
63+
isSign = false,
4464
url = '',
4565
method = 'get',
4666
header = 'application/x-www-form-urlencoded; charset=UTF-8',
@@ -82,6 +102,18 @@ export function weiAxios(
82102
}
83103
/**axios请求参数添加随机字符串*/
84104
data['__t'] = (new Date()).getTime();
105+
//如果需要计算签名
106+
if (isSign) {
107+
let urlParamMap = getUrlParamMap(url);
108+
for (let key in urlParamMap) {
109+
if (!urlParamMap.hasOwnProperty(key)) {
110+
return;
111+
}
112+
data[key] = urlParamMap[key];
113+
}
114+
let asciiStr = that.$globalFun.sortAscii(data);
115+
data['__sign'] = that.$globalFun.md5NoSalt(asciiStr);
116+
}
85117
/**axios请求处理不同请求方式时的参数*/
86118
method = method.toUpperCase();
87119
if (method === 'GET') {
@@ -147,6 +179,7 @@ export function weiAxios(
147179
* @param url
148180
* @param method
149181
* @param data
182+
* @param isSign 是否需要计算签名
150183
* @param filename 文件名字
151184
* @param timeShowLoadAnimation 多长时间之后显示加载中动画,单位毫秒
152185
* @param success
@@ -158,6 +191,7 @@ export function weiAxiosDown(
158191
url = '',
159192
method = 'post',
160193
data = {},
194+
isSign = false,
161195
filename = '新建文件',
162196
timeShowLoadAnimation = 555,
163197
success = function () {
@@ -189,6 +223,18 @@ export function weiAxiosDown(
189223
_axios['headers'][that.$global.GLOBAL.token] = that.$globalFun.getSessionStorage(`token`) || '';
190224
/**axios请求参数添加随机字符串*/
191225
data['__t'] = (new Date()).getTime();
226+
//如果需要计算签名
227+
if (isSign) {
228+
let urlParamMap = getUrlParamMap(url);
229+
for (let key in urlParamMap) {
230+
if (!urlParamMap.hasOwnProperty(key)) {
231+
return;
232+
}
233+
data[key] = urlParamMap[key];
234+
}
235+
let asciiStr = that.$globalFun.sortAscii(data);
236+
data['__sign'] = that.$globalFun.md5NoSalt(asciiStr);
237+
}
192238
/**axios请求处理不同请求方式时的参数*/
193239
method = method.toUpperCase();
194240
if (method === 'GET') {

vue/src/utils/global_function.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,18 @@ function md5(str) {
340340
return CryptoJs.MD5(str).toString().toUpperCase();
341341
}
342342

343+
/**
344+
* md5加密没有加密盐
345+
* @param str
346+
* @returns {*}
347+
*/
348+
function md5NoSalt(str) {
349+
if (null == str) {
350+
return null;
351+
}
352+
return CryptoJs.MD5(str).toString().toUpperCase();
353+
}
354+
343355
/**
344356
* 获取session存储的数据
345357
* @param key
@@ -392,6 +404,28 @@ function setLocationStorage(key, value = '') {
392404
localStorage.setItem(key, JSON.stringify(value));
393405
}
394406

407+
/**
408+
* 对象进行ascii排序
409+
* @param obj
410+
* @returns {*}
411+
*/
412+
function sortAscii(obj) {
413+
if (null == obj) {
414+
return null;
415+
}
416+
let arr = [];
417+
let index = 0;
418+
for (let key in obj) {
419+
arr[index] = key;
420+
index++;
421+
}
422+
let str = '';
423+
arr.sort().forEach(value => {
424+
str += `${value}=${('' + obj[value]).replace(/(^\s*)|(\s*$)/g, "")}&`;
425+
});
426+
return str.substr(0, str.length - 1);
427+
}
428+
395429
/**
396430
* 将方法暴露出去
397431
*/
@@ -412,8 +446,10 @@ export default {
412446
base64Encrypt,
413447
base64Decrypt,
414448
md5,
449+
md5NoSalt,
415450
getSessionStorage,
416451
setSessionStorage,
417452
getLocationStorage,
418-
setLocationStorage
453+
setLocationStorage,
454+
sortAscii
419455
};

0 commit comments

Comments
 (0)