java中Aop面向切面编程实例,权限校验AppKeyValidation及数据解密及ResourceBundle加载文件。
使用场景:不同系统间当登录或者请求相关接口时校验是否含有AppKey等信息。如果有的话,可以处理相关的业务逻辑,如果没有的话,则返回相应的返回信息,前后端接口相关信息约定好,相关数据可以进行加密。
对相关的接口添加自定义注解,Aop进行方法的增加,对相关自定义注解进行校验。
1.自定义注解设置
package com.yl.oms.api.base.annotations.appkey;
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 org.springframework.web.bind.annotation.Mapping;
/**
* 抽象验证AppKey接口规范
* @author Tolk
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface AppKeyValidation {
}
2.接口添加@AppKeyValidation注解,对接口进行方法的增强
/**
* CRM传递项目信息同步至EHR
* @return result
*/
@AppKeyValidation
@ResponseBody
@RequestMapping(value = "/synProjectFromCRM")
public ResultMessage synProjectFromCRM(@RequestBody String jsonParam,HttpServletRequest request,String appKey){
logger.info("[synProjectFromCRM]:CRM传递项目信息同步至EHR;time=" + DateConvertUtils.getTime());
logger.info("[synProjectFromCRM]:param:" + jsonParam);
return apiCrmService.synProjectFromCRM(jsonParam);
}
3.配置文件的添加 config.properties
#接口appKey验证 一下的若包含则不做 key+param hash比较,多个逗号分隔;
appkeys = CRM-EHR,TEST-KEY
4.具体的切面类的编写,校验添加了自定义注解接口相关信息
校验主要是对接口方法中的参数,类型进行校验。对数据进行解密处理,然后调用执行相关接口处理相关业务逻辑。
package com.yl.oms.api.base.annotations.appkey;
import com.yl.entity.vo.base.ResultMessage;
import com.yl.facade.api.ApiReceiveQueueService;
import com.yl.oms.api.util.DESUtil;
import com.yl.util.lang.StringUtils;
import net.sf.json.JSONObject;
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.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ResourceBundle;
/**
* APPKey验证类AOP执行调度
* @author Tolk
*/
@Aspect
@Component
@Order(100)
public class AppKeyValidationAspect {
private static Logger logger = LoggerFactory.getLogger(AppKeyValidationAspect.class);
@Autowired
ApiReceiveQueueService apiReceiveQueueService;
/**
* Around
* 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
* 注意:当核心业务抛异常后,立即退出,转向AfterAdvice
* 执行完AfterAdvice,再转到ThrowingAdvice
* @param pjp
* @return
* @throws Throwable
*/
@Around("@annotation(com.yl.oms.api.base.annotations.appkey.AppKeyValidation)")
// @Pointcut("execution(public * com.yl.oms.api.controller.cti.AddCtiCallRecordController*add(..)) && @annotation(com.yl.oms.api.base.annotations.appkey.AppKeyValidation)")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
Object retVal = null;
// String resultStr = null;
MethodSignature ms=(MethodSignature) pjp.getSignature();
Method method=ms.getMethod();
// AppKeyValidation appKeyValidation = method.getAnnotation(AppKeyValidation.class);
//获取方法Code
String methodName = method.getName();
ResultMessage sApiValidationResult = null;
String appKey = null;
String appApiHash = null;
String needEncrypt = null;
String sOldParam = null;
String sNewParam = null;
String secretKeyStr = null;
try{
//参数验证
if(pjp.getArgs().length != 3){
sApiValidationResult = new ResultMessage("接口参数异常, 非约定规范(指定的三个参数)! ");
}else{
HttpServletRequest request = (HttpServletRequest) pjp.getArgs()[1];
appKey = request.getHeader("Dapi-App-Key");
appApiHash = request.getHeader("Dapi-Hash");
needEncrypt = request.getHeader("Dapi-Encrypt");
sOldParam = (String) pjp.getArgs()[0];
secretKeyStr = appKey;
if(appKey != null && appKey.length() < 32){
secretKeyStr = DESUtil.string2MD5(appKey);
}
if(appKey == null || "".equals(appKey)){
sApiValidationResult = new ResultMessage("AppKey参数验证失败! ");
}else if(appApiHash == null || "".equals(appApiHash)){
sApiValidationResult = new ResultMessage("AppApiHash参数验证失败! ");
}else{
//验证ApiHash合法性
String sApiHash = DESUtil.string2MD5(appKey + sOldParam);
boolean isCheckPass = (sApiHash != null && appApiHash.equals(sApiHash));
//获取config.properties中的配置信息
ResourceBundle.clearCache();
ResourceBundle bundle = ResourceBundle.getBundle("config");
String unCheckAppkeys = StringUtils.safeToString(bundle.getString("appkeys"),"CRM-EHR");
//CRM接口不做hash验证 只验证 appKey = CRM-EHR
if(unCheckAppkeys.contains(appKey)){
isCheckPass = true;
}
if(isCheckPass){
try{
if(needEncrypt != null && "true".equals(needEncrypt)){
sNewParam = DESUtil.decrypt(sOldParam, secretKeyStr);
}else{
sNewParam = sOldParam;
}
pjp.getArgs()[0] = sNewParam;
pjp.getArgs()[2] = appKey;
try{
//调用执行原代码
retVal = pjp.proceed(pjp.getArgs());
if(retVal == null){
sApiValidationResult = new ResultMessage(true, "成功");
}else if(method.getReturnType() == String.class){
sApiValidationResult = new ResultMessage(true, retVal.toString());
}else if(method.getReturnType() == ResultMessage.class){
sApiValidationResult = (ResultMessage)retVal;
}
}catch(Exception e){
sApiValidationResult = new ResultMessage("执行API处理失败!Message: " +e.toString());
}
}catch(Exception e){
sApiValidationResult = new ResultMessage("参数内容解密失败!");
}
}else{
sApiValidationResult = new ResultMessage("AppKey和 参数内容 合法性 验证失败!");
}
}
}
}catch(Exception e){
sApiValidationResult = new ResultMessage("程序异常, 请联系接口研发人员, ErrorMessage: " + e.toString());
logger.error("API方法异常("+methodName+"), 程序执行异常, Message: " + e.toString() );
}
if(sApiValidationResult == null){
sApiValidationResult = new ResultMessage("返回值异常,请联系研发人员!");
}
//当失败的时候打印参数
if(sApiValidationResult != null && !sApiValidationResult.isSuccess()){
logger.info("invokeError-" + methodName + ", appKey: " + appKey + ", appApiHash: " + appApiHash
+ ", Result: "+ sApiValidationResult+", Param: " + (sNewParam == null ? sOldParam : sNewParam));
}
if(sApiValidationResult != null && secretKeyStr != null && "true".equals(needEncrypt)){
if(method.getReturnType() == String.class){
return DESUtil.encrypt(sApiValidationResult.toString(), secretKeyStr);
}
}
if(method.getReturnType() == String.class){
retVal = sApiValidationResult.toString();
}else if(method.getReturnType() == ResultMessage.class){
retVal = sApiValidationResult;
}else if(method.getReturnType() == JSONObject.class){
retVal = JSONObject.fromObject(sApiValidationResult);
}else if(method.getReturnType() == void.class){
retVal = null;
}
return retVal;
}
}
总结:主要是通过自定义注解的使用,AOP面向切面编程思想具体使用,对添加了自定义注解的接口方法的增强。然后处理相关的业务逻辑,这里主要是权限校验,数据解密业务场景的使用。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/80410.html