背景
项目部分接口需要进行简单的验签,故使用aop配合注解使用。
注解的定义
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SignAnnotation {
}
SignAnnotation 注解是一个方法注解
AOP的定义
@Order(2)
@Aspect
@Component
public class SignatureAuthAspect {
/** 加签秘钥, 用作md5加密的掩码 */
public static final String SECRET = "xxx";
/** 切点 */
@Pointcut("@annotation(com.mogucaifu.financial.shop.domain.SignAnnotation)")
public void pointCut(){}
/**
* 环绕检查参数授权等
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("pointCut()")
public Object apiAuthAround(ProceedingJoinPoint joinPoint) throws Throwable {
/** 从spring上下文获取request对象 */
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
/** 解析请求参数, 并将参数放置到ThreadLocal中去 */
Map<String, Object> requestParams = parserRequestParams(request);
String requestSign = (String)requestParams.get("sign");
if(StringUtils.isEmpty(requestSign)){
throw new MessageException(StringConst.ERRCODE_PARAMETER_NOT_EMPTY, String.format(StringConst.ERRCODE_PARAMETER_NOT_EMPTY_MSG, "签名"));
}
/** 签名参数sign不参与后续加签步骤 */
requestParams.remove("sign");
String signature = createSignature(requestParams);
if(!requestSign.equals(signature)){
throw new MessageException(StringConst.ERRCODE_X, "非法的signature");
}
return joinPoint.proceed();
}
/**
* 解析request请求参数
* @param request
* @return Map
*/
protected Map<String, Object> parserRequestParams(HttpServletRequest request){
//省略
return params;
}
/**
* 读取body体内容
* @param request
* @param charsetName
* @return
*/
protected String readPostBodyContent(HttpServletRequest request, String charsetName) {
//省略
return contentBuf.toString();
}
/**
* 加密签名
* @param requestParams
* @return
*/
private String createSignature(Map<String, Object> requestParams) {
//省略加签操作
}
}
使用Around通知进行检查。获取spring上下文获取reques对象,对所有参数进行加签操作,验证通过后进入方法的执行。
使用
@SignAnnotation
@RequestMapping(value = "getxxx", method = RequestMethod.GET)
public WebResult getxxx(@PathVariable String channel, HttpServletRequest request){
//....省略
}