通過RequestBodyAdvice和自定義注解,實現加密參數自動解密


RequestBodyAdvice接口

它是SpringMVC提供的一個接口,類注釋如下

允許在請求體被讀取並轉換為Object之前對請求進行定制,也允許在結果對象作為@RequestBody或HttpEntity方法參數傳遞給控制器方法之前對其進行處理。 該接口的實現可以直接注冊到RequestMappingHandlerAdapter,或者更有可能使用@ControllerAdvice注釋,在這種情況下它們會被自動檢測。

它提供了四個方法

  • supports:首次調用,判斷這個攔截器是否適用這次請求,返回boolean
  • beforeBodyRead:在轉換至Controller參數對象之前調用,加工請求頭和請求體
  • afterBodyRead:在轉換至Controller參數對象之后調用,處理這個對象
  • handleEmptyBody:當參數為空時調用,可以返回請求體,也可以返回null正常觸發Body為空的報錯

實現方式

我們的思路是這樣的,首先自定義一個注解@Encrypt,用在被@RequestBody標記的參數上。

然后我們實現RequestBodyAdvice接口,首先實現supports接口,通過判斷是否標注了我們的注解,來決定是否進行解密操作

  @Override  
   public boolean supports(
      MethodParameter methodParameter, Type type, 
      Class<? extends HttpMessageConverter<?>> aClass) {
        return methodParameter.hasParameterAnnotation(Encrypt.class);
  }  

然后,我們在beforeBodyRead方法中,實現我們解密的核心操作

    @Override  
    public HttpInputMessage beforeBodyRead(
      HttpInputMessage httpInputMessage, 
      MethodParameter methodParameter, Type type, 
      Class<? extends HttpMessageConverter<?>> aClass) throws IOException {

        return new HttpInputMessage() {
            @Override
            public InputStream getBody() throws IOException {
                logger.info("請求頭參數:"+ httpInputMessage.getHeaders());
                logger.info("在此處去掉請求參數外層data");
                String body = IOUtils.toString(httpInputMessage.getBody());
                JSONObject jasonObject = JSONObject.parseObject(body);
                String content = (String)jasonObject.get("data");
                //進行解密操作
                String after = null;
                try {
                    DESUtils desUtils = new DESUtils(desKey);
                    after = desUtils.decryptString(content);
                } catch (Exception e) {
                    logger.error("解密失敗");
                }
                return new ByteArrayInputStream
                        (after.getBytes(StandardCharsets.UTF_8));

            }
  
            @Override  
            public HttpHeaders getHeaders() {
                return httpInputMessage.getHeaders();  
            }  
        };  
    }  

afterBodyRead接口直接返回Object,不做任何其他處理

根據類文檔說明,要向讓這個自定義的RequestBodyAdvice起作用,我們可以給它添加上@ControllerAdvice注解,他就可以自動注冊到Spirng容器,而后注冊到RequestMappingHandlerAdapter

至此,我們就實現了我們的功能。

思考

我們可以看到,在SpringMVC中有很多類似的Adapter,它們大部分都為我們提供了簡單的擴展方式。通過探究這些接口在系統中生效的原理,也是我們看SpringMVC源碼很好的切入點


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM