SpringBoot中使⽤切⾯的每次传的参数,进⾏解析,验签,并
返回解码后的参数
⽬的,在每次请求的时候,对每次传的参数,进⾏解析,验签,并返回解码后的参数,以json传递;
例⼦背景:
IOT平台提供对外可访问的接⼝,需要对所有参数的传递做到不泄露、认证的⽬的;所以需要在每次请求的时候:
1、对需要传递的参数进⾏加密,
byte[] encrypt = encrypt(content, "6AEB57F8DA93860A19514592A154BEF8");
String hexStr = parseByte2HexStr(encrypt);
System.out.println("加密后的2进制密⽂:" + hexStr);
2、通过对时间戳、随机数、请求类型、路径和加密后的参数进⾏加签
String method = "POST";
String timestamp = String.valueOf(System.currentTimeMillis());
System.out.println("timestamp:"+timestamp);
String salt = String.valueOf((int)((Math.random()*9+1)*100000));
System.out.println("salt:"+salt);
String url ="/iot/open/device/v1/sync";
String sign = generateSign(salt,timestamp,"407af810068111ea95f4852d6a259567",method,url,hexStr,
"b645d880068111ea8f09cf8592eb9fbc");
System.out.println("sign:"+sign);
/**
* 签名算法
*
* @param salt 随机数
* @param timestamp 时间戳
* @param appKey 应⽤Key
* @param httpRequestMethod 添加POST
* @param canonicalURI 接⼝地址
* @param canonicalParameterString 加签内容
*/
public static String generateSign(String salt, String timestamp, String appKey,
String httpRequestMethod, String canonicalURI, String canonicalParameterString,
String appSecret) {
String sign = null;
try {
String canonicalHeaders = salt + timestamp + appKey;
String stringToSign = httpRequestMethod + "\n"
+ canonicalURI + "\n"
+ canonicalParameterString + "\n"
+ canonicalHeaders;
Mac mac = null;
mac = Instance("HmacSHA256");
SecretKeySpec sk = new Bytes(StandardCharsets.UTF_8),
"HmacSHA256");
mac.init(sk);
sign = Hex
.encodeHexString(mac.Bytes(StandardCharsets.UTF_8)));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
<(
"⽣成签名失败,appKey:{},salt:{},timestamp:{},httpRequestMethod:{},canonicalURI:{},canonicalParameterString:{}", appKey, salt, timestamp, httpRequestMethod, canonicalURI, canonicalParameterString);
e.printStackTrace();
}
return sign;
}
3、最后发送请求
此时,参数是加密的,请求头中包含着约定的签名、时间戳、随机数、约定的key;已经对传递的参数做了加密,页⾝份的加签
后⾯开始切⾯编程:
4、创建注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SignValidate {
/**
* ⽅法上⽤于接收接收业务参数字段名称
*
* @return 参数名称
*/
String paramName() default "signParam";
/**
* 参数中加签字段的名称
*
* @return 加签字段的名称
*/
String signName() default "parameters";
}
使⽤的时候
只需要在⽅法上加上:
@SignValidate
@PostMapping("/v1/sync")
public CommonResponse syncOne(HttpServletRequest request,
@RequestBody SignParamDTO signParam) {
log.info("设备同步请求ip为{},参数为{}", Ip(request), Parameters()); return CommonResponse.success(deviceSyncService.Parameters())); }
5、开始切⾯类
HttpServletRequest的功能可以分为以下⼏种:
封装了请求头数据;
封装了请求正⽂数据,如果是GET请求,那么就没有正⽂;
request是⼀个域对象,可以把它当成Map来添加获取数据;
做请求的转发
package cn.video110.iot.open.aspect;
import cn.video110.ode.SignErrorCode;
import cn.video110.iot.open.utils.SignUtil;
import cn.video110.starter.mvcmon.CommonResponse;
import flect.Field;
import flect.Method;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
slf4j.Slf4j;
import org.apachemons.lang3.ArrayUtils;
import org.apachemons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.flect.MethodSignature;
import org.springframework.stereotype.Component;
import org.t.request.RequestContextHolder;
import org.t.request.ServletRequestAttributes;
/**
* 参数签名验证
* @author
* @date 2020/07/23
*/
@Slf4j
@Component //组件
public class SignValidateAspect {
private static String APP_KEY = "407af810068111ea95f4852d6a259567";
private static String APP_SECRET = "b645d880068111ea8f09cf8592eb9fbc";
private static String APP_PASSWORD = "6AEB57F8DA93860A19514592A154BEF8"; /**
* header 中验签参数
*/
private final String[] SIGN_HEADER = new String[]{
"x-clss-iot-authorization",
"x-clss-iot-timestamp",
"x-clss-iot-salt",
"x-clss-iot-appkey"
};
private final String headerAuthorization = "x-clss-iot-authorization";
private final String headerTimestamp = "x-clss-iot-timestamp";
private final String headerSalt = "x-clss-iot-salt";
private final String headerAppKey = "x-clss-iot-appkey";
/**
* 签名验证表⽰所有的带有SignValidate的注解
*/
@Pointcut("@annotation(cn.video110.iot.open.aspect.SignValidate)")
public void signValidate() {
}
@Around("signValidate()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Object response = null;
ServletRequestAttributes attributes = (ServletRequestAttributes)
// 获取当前的Request的实体
HttpServletRequest request = Request();
Map<String, String> signHeader = getSignHeader(request);
//校验header
CommonResponse checkResult = checkHeader(signHeader);
if (!checkResult.isStatus()) {
return checkResult;
}
checkResult = verifySignAndDecrypt(request, signHeader, joinPoint);
if (!checkResult.isStatus()) {
return checkResult;
}
response = joinPoint.proceed((Object[]) Obj());
return response;
}
/**
* 获取header签名⽤的字段
*/
private Map<String, String> getSignHeader(HttpServletRequest request) {
Enumeration<String> headerNames = HeaderNames();
Map<String, String> headerMap = new HashMap();
List<String> signList = Arrays.asList(SIGN_HEADER);
while (headerNames.hasMoreElements()) {
String headerName = Element();
if (ains(headerName)) {
String headerValue = Header(headerName);
headerMap.put(headerName, headerValue);
}
}
return headerMap;
/
**
* 校验header内参数
*
* @param signHeader header签名参数
* @return CommonResponse 校验结果
*/
private CommonResponse checkHeader(Map<String, String> signHeader) {
if (!ainsKey(headerAuthorization) || StringUtils
.(headerAuthorization))) {
(SignErrorCode.NON_AUTHORIZATION);
}
if (!ainsKey(headerTimestamp) || StringUtils
.(headerTimestamp))) {
(SignErrorCode.NON_TIMESTAMP);
}
if (!ainsKey(headerSalt) || StringUtils
.(headerSalt))) {
(SignErrorCode.NON_SALT);
}
if (!ainsKey(headerAppKey) || StringUtils
.(headerAppKey))) {
(SignErrorCode.NON_APPKEY);
}
return CommonResponse.success();
}
private CommonResponse<Object[]> verifySignAndDecrypt(HttpServletRequest request, Map<String, String> signHeader,
ProceedingJoinPoint joinPoint) {
//获取参数
Object[] args = Args();
CommonResponse response = null;
// 获取连接点的⽅法签名对象;
Signature signature = Signature();
MethodSignature methodSignature = (MethodSignature) signature;
String[] params = ParameterNames();
if (params.length == 0) {
log.info("当前切⼊点⽅法{}没有需要验签的参数。", Name());
return CommonResponse.success(args);
}
// 获得注解中的信息
Method method = Method();
SignValidate signValidate = Annotation(SignValidate.class);
Integer index = ArrayUtils.indexOf(params, signValidate.paramName());
if (args[index] != null) {
String sign = getSign(args[index], signValidate.signName());
if (StringUtils.isBlank(sign)) {
(SignErrorCode.NON_PARAM);
}
response = verifySign(request, signHeader, sign);
if (!response.isStatus()) {
return response;
}
args[index] = decryptParam(args[index], signValidate.signName(), APP_PASSWORD); }
return CommonResponse.success(args);
}
/**
* @param request 请求
* @param signHeader 签名header
* @param parameters 参数
* @return 验签结果
*/
private CommonResponse verifySign(HttpServletRequest request, Map<String, String> signHeader, String parameters) {
//根据appKey查询
String appSecret = APP_SECRET;
//验签
String method = Method();
String canonicalURI = ServletPath() + PathInfo();
String salt = (headerSalt);
String timestamp = (headerTimestamp);
String appKey = (headerAppKey);
String sign = SignUtil
.generateSign(salt, timestamp, appKey, method, canonicalURI, parameters, appSecret);
if (!Objects.equals(sign, (headerAuthorization))) {
(SignErrorCode.VERIFY_FAIL);
}
return CommonResponse.success();
}
private String getSign(Object signObject, String signName) {
Class<?> resultClass = Class();
Field[] fieldInfo = DeclaredFields();
for (Field field : fieldInfo) {
if (signName.Name())) {
field.setAccessible(true);
Object fieldValue = null;
try {
fieldValue = (signObject);
if (fieldValue == null) {
return null;
}
String();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return null;
}
springboot推荐算法/**
* 解密参数
*
* @param args ⼊参实体
* @param signName 签名字段名称
* @param appPassword 解密密码
* @return 解密后的参数
*/
private Object decryptParam(Object args, String signName, String appPassword) {
Class<?> resultClass = Class();
Field[] fieldInfo = DeclaredFields();
for (Field field : fieldInfo) {
if (signName.Name())) {
field.setAccessible(true);
Object fieldValue = null;
try {
fieldValue = (args);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论