java请求参数防修改_SpringMVC接⼝防数据篡改和重复提交本⽂实例为⼤家分享了Spring MVC接⼝防数据篡改和重复提交的具体代码,供⼤家参考,具体内容如下
⼀、⾃定义⼀个注解,此注解可以使⽤在⽅法上或类上
使⽤在⽅法上,表⽰此⽅法需要数据校验
使⽤在类上,表⽰此类下的所有⽅法需要数据校验
此注解对⽆参数⽅法不起作⽤
import org.springframework.stereotype.Component;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface DataValidate {
}
⼆、⾃定义拦截,拦截前端所有请求
1、检查此接⼝调⽤的⽅法或⽅法所在的类是否使⽤了DataValidate注解,若没有使⽤,表⽰此接⼝不需要校验数据;
2、若使⽤了注解,再检查此⽅法有没有⼊参,若没有⼊参,不需要校验数据,否在需要校验;
3、把前端传来的所有参数 (除了签名参数)按照参数升序⽣成⼀个json字符串(使⽤TreeMap⽅式⾃动排序);
4、把⽣成的json字符串通过MD5加密的结果和前端传的签名值对⽐,若不相等,表⽰此数据被篡改过,否在没有被篡改过;
5、数据是否被篡改校验完毕,若前端传了⽤户唯⼀标⽰(token),表⽰需要校验数据是否重复提交;
6、若签名和上次提交的数据的签名相等,表⽰是重复提交数据,若不相等,把签名保存下来,表⽰数据不是重复提交。
import java.security.MessageDigest;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import urrent.ConcurrentHashMap;
import javax.annotation.PreDestroy;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import MethodParameter;
import org.hod.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.alibaba.fastjson.JSON;
/**
* 防数据被篡改和重复提交
*/
public class DataValidateInterceptor extends HandlerInterceptorAdapter implements Runnable {
public static Map userToken = new ConcurrentHashMap<>();
// 过期时间
private static long EXPIRED_TIME = 3600000;
private static String TOKEN_NAME = "token";
private static String SIGN_NAME = "sign";
private volatile boolean shutDown;
public DataValidateInterceptor(@Value("${pired_time}") String expiredTime,
@Value("${ken_name}") String tokenName,
@Value("${data_interceptor.sign_name}") String signName) {
if (null != expiredTime && !"".equals(expiredTime)) {
EXPIRED_TIME = Long.parseLong(expiredTime);
}
if (null != tokenName && !"".equals(tokenName)) {
TOKEN_NAME = tokenName;
}
提交的东西不能更改if (null != signName && !"".equals(signName)) {
SIGN_NAME = signName;
}
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (validate(request, response, handler)) {
/**
* 实现返回提⽰数据
*/
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
return false;
}
return true;
}
private boolean validate(HttpServletRequest request, HttpServletResponse response, Object handler) { if (handler instanceof HandlerMethod) {
Class> clazz = ((HandlerMethod) handler).getBeanType();
DataValidate dataValidate = Annotation(DataValidate.class);
if (null == dataValidate) {
dataValidate = ((HandlerMethod) handler).getMethodAnnotation(DataValidate.class);
}
if (dataValidate != null) {
MethodParameter[] methodParameters = ((HandlerMethod) handler).getMethodParameters();
if (null == methodParameters || methodParameters.length <=0) {
// ⽅法没有⼊参不需要校验
return false;
}
// 需要校验
String sign = Parameter(SIGN_NAME);
Map params = ParameterMap();
Set paramNames = params.keySet();
Map paramsMap = new TreeMap<>();
for (String paramName : paramNames) {
if (paramName.equals(SIGN_NAME)) {
continue;
}
paramsMap.put(paramName, Parameter(paramName));
}
String paramString = JSONString(paramsMap).replaceAll(" ", "");
String MD5Sign = MD5(paramString);
if (!sign.equals(MD5Sign)) {
// 数据被篡改
return true;
}
String token = Parameter(TOKEN_NAME);
if (token != null) {
if (ainsKey(token)) {
TokenValue tokenValue = (token);
if (Value().equals(sign)) {
// 数据已经提交过
return true;
} else {
tokenValue.setValue(sign);
}
} else {
userToken.put(token, new TokenValue(sign));
}
}
}
}
return false;
}
@Override
public void run() {
try {
while (!shutDown) {
synchronized (this) {
wait(EXPIRED_TIME);
Set keys = userToken.keySet();
for (String key : keys) {
if (((key).getExpiredTime() + EXPIRED_TIME) <= System.currentTimeMillis()) { ve(key);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@PreDestroy
public void custDestroy() {
shutDown = true;
synchronized (this) {
notifyAll();
}
}
private static class MD5 {
/**
* 向getMD5⽅法传⼊⼀个你需要转换的原始字符串,将返回字符串的MD5码*
* @param code 原始字符串
* @return 返回字符串的MD5码
*/
private static String getMD5(String code) {
try {
MessageDigest messageDigest = Instance("MD5"); byte[] bytes = Bytes();
byte[] results = messageDigest.digest(bytes);
StringBuilder stringBuilder = new StringBuilder();
for (byte result : results) {
// 将byte数组转化为16进制字符存⼊stringbuilder中
stringBuilder.append(String.format("%02x", result));
}
String();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
}
public class TokenValue {
private String value;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论