使用aop加解密http接口

背景

最近在寫一個小程序接口,因爲安全性比較高,所以須要給請求參數和響應進行加密處理。若是在每一個方法上都加密解密,那樣代碼就顯得太繁瑣了並且工做量會加大。因此,咱們會統一進行加解密處理,一種比較傳統的方式就是經過攔截器進行攔截處理。在這裏咱們選擇經過使用spring的aop來實現。java

處理方案

1.比較spring的五種通知後。很容易發現,環繞通知能夠解決咱們的問題,環繞通知有哪些特色呢?web

  • 環繞通知是全部通知類型中功能最爲強大的, 可以全面地控制鏈接點. 甚至能夠控制是否執行鏈接點 。
  • 對於環繞通知來講, 鏈接點的參數類型必須是 ProceedingJoinPoint. 它是 JoinPoint的子接口, 容許控制什麼時候執行, 是否執行鏈接點 。
  • 在環繞通知中須要明確調用 ProceedingJoinPoint 的 proceed() 方法來執行被代理的方法. 若是忘記這樣作就會致使通知被執行了, 但目標方法沒有被執行 。
  • 環繞通知的方法須要返回目標方法執行以後的結果, 即調用 joinPoint.proceed(); 的返回值, 不然會出現空指針異常

2.具體看一下代碼如何實現。算法

  • aspect類
import com.legendnet.elecmeter.utils.EncryptUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author 情繫IT
 * @Description
 * @Date 2019-12-04 14:55
 */
@Aspect
@Slf4j
@Component
public class HttpAspect {

    // 定義切點controller包及子包下面的全部方法
    @Pointcut("execution(public * com.legendnet.elecmeter.controller..*.*(..))")
    public void httpRequest(){}

    @Around("httpRequest()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Exception {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // target 判斷來源而後根據不一樣的解密算法解密
        String target = request.getParameter("target");
        String paramCode = request.getParameter("param_code");
        paramCode = paramCode.replaceAll(" ", "+");

        if(StringUtils.isNotBlank(paramCode)){
            if("miniProgram".equals(target)){
                paramCode = EncryptUtils.aesDecrypt(paramCode);
            }

            log.info("請求參數爲:【{}】",paramCode);
        }
        request.setAttribute("param_code",paramCode);
        Object proceed = "";
        try {
            proceed = proceedingJoinPoint.proceed();
            if("miniProgram".equals(target)){
                proceed = EncryptUtils.aesEncrypt(proceed.toString());
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }
}
  • controller類
import com.alibaba.fastjson.JSON;
import com.legendnet.elecmeter.common.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author 情繫IT
 * @Description
 * @Date 2019-12-04 15:23
 */
@RestController
@Slf4j
public class TestController {

    @RequestMapping("test")
    public String test(HttpServletRequest request){
        String param_code = request.getAttribute("param_code").toString();
        log.info("我已接收到參數,參數爲:【{}】",paramCode);

        ResultBean resultBean = new ResultBean();
        resultBean.fillData("這就是個人響應");
        return JSON.toJSONString(resultBean);
    }
}

3.因爲小程序和app的加密方式不一樣,爲了代碼的高可用,咱們經過target參數來判斷其來源,而後選擇不一樣的加解密方式進行處理。spring

大功告成,接下來安心的寫接口就能夠了,媽媽不再用擔憂我去處理加密解密的問題了。apache

若是文章對您有幫助,請記得點贊關注喲~ 歡迎你們關注個人公衆號:情繫IT,每日推送技術文章供你們學習參考。
相關文章
相關標籤/搜索