利用Spring AOP解密請求參數,實作接口安全認證
在寫接口的時候經常會遇到需要進行安全認證的場景,如果是一兩個接口寫個公共的安全檢查方法,然後每個接口去調用一下就可以了,但是如果接口很多,這個過程就顯得有點繁瑣了,由于工作需要是以看了幾篇通過SpringAOP實作的,自己也在項目中實驗了一下,代碼如下。
Spring AOP有什麼環繞通知,前置後置通知,大家可以具體看下關于這幾個通知的含義及用法。
自定義一個注解,@Security.java,代碼如下
package com.light.api.helper.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.light.api.constant.Authority;
/**
*
* @Description: 自定義安全驗證注解
*
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Security {
/**
*
* @Title: sign
* @Description: 簽名字段
* @return String[]
* @throws
*/
String[] sign() default {};
/**
*
* @Title: field
* @Description: 加密的字段
* @return String[]
* @throws
*/
String[] field() default {};
/**
*
* @Title: method
* @Description:
* @return Authority
* @throws
*/
Authority method() default Authority.DEFAULT_ACCESS;
}
Spring AOP的具體實作類
package com.light.api.helper.aop;
import java.util.Arrays;
import javax.annotation.Resource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
*
* @Description: 接口安全驗證AOP
*
*/
@Aspect
@Component
public class SecurityAOP {
private static final Logger logger = LoggerFactory.getLogger(SecurityAOP.class);
@Resource
private TrafficPermissionManager<TrafficPermission> trafficPermissionManager;
/**
* 在所有标注@Security的地方切入
*/
@Before("@annotation(com.light.api.helper.annotation.Security)")
public void beforeExec(JoinPoint joinPoint) throws IOException {
}
@After("@annotation(com.light.api.helper.annotation.Security)")
public void afterExec(JoinPoint joinPoint) {
}
@AfterThrowing(value = "@annotation(com.light.api.helper.annotation.Security)", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
logger.error("@AfterThrowing-->The method {} occurs exception:{}", methodName, ex);
}
@Around("@annotation(com.light.api.helper.annotation.Security)")
public Object around(ProceedingJoinPoint point) throws Throwable {
logger.info("@Around start ...");
MethodSignature ms = (MethodSignature) point.getSignature();
Authority authority = ms.getMethod().getAnnotation(Security.class).method();
String[] signs = ms.getMethod().getAnnotation(Security.class).sign();
String[] fields = ms.getMethod().getAnnotation(Security.class).field();
Object[] args = point.getArgs();
for (int i = ; i < args.length; i++) {
if (args[i] instanceof SecurityRequest) {
// 需要實作的業務邏輯
// 在這兒可以對參數進行解密操作,并指派給args[i]中,傳遞到目标方法中。然後在目标方法中就可以使用已經解密的參數了。
}
if (args[i] instanceof String) {
// 需要實作的業務邏輯
}
}
// 這個很重要
Object response = point.proceed(args);
// 在這塊可以記日志。
return response;
}
}
因為使用的是注解方式的AOP,是以隻需要在SpringMVC.xml配置檔案中添加下面這段代碼就可以了
controller中的代碼如下:
@Security(sign = { "aaa", "bbb" }, fields = { "aaa", "bbb" }, method = Authority.TEST)
@RequestMapping(value = { "/test", "/test1" }, method = { RequestMethod.POST }, produces = {
"application/json" }, consumes = { "application/json" })
@ResponseBody
public SecurityResponse test(@RequestBody TrafficRequest trafficRequest, String request) {
//具體實作
return null;
}
到這裡基本就可以了,大家可以根據需要具體實作。