java中Aop面向切面编程实例,权限校验AppKeyValidation及数据解密及ResourceBundle加载文件。

导读:本篇文章讲解 java中Aop面向切面编程实例,权限校验AppKeyValidation及数据解密及ResourceBundle加载文件。,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

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

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!