<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于 RequestBodyAdvice 與 ResponseBodyAdvice 實(shí)現(xiàn)統(tǒng)一加密和解密

          共 8652字,需瀏覽 18分鐘

           ·

          2021-05-24 21:48

           在日常開(kāi)發(fā)中,有時(shí)候經(jīng)常需要和第三方接口打交道,有時(shí)候是我方調(diào)用別人的第三方接口,有時(shí)候是別人在調(diào)用我方的第三方接口,那么為了調(diào)用接口的安全性,一般都會(huì)對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行加密操作,如果每個(gè)接口都由我們自己去手動(dòng)加密和解密,那么工作量太大而且代碼冗余。那么有沒(méi)有簡(jiǎn)單的方法,借助 spring 提供的  RequestBodyAdvice 和 ResponseBodyAdvice 可以實(shí)現(xiàn)解密和加密操作。

           

          需求:

          • 后臺(tái)方法上如果有 @Encrypt 注解和 @RequestBody 修飾的方法,需要進(jìn)行參數(shù)的解密    

          • 后臺(tái)方法上如果有 @Encrypt 注解和 @ResponseBody 修飾的方法,需要進(jìn)行參數(shù)的加密

          • 加密和解密規(guī)則

                     加密:對(duì)返回的值中增加 -encrypt 值

                     解密:對(duì)傳入的值中刪除 -encrypt 值

          注:

          • @Encrypt 為自定義的一個(gè)注解。

          • 此處為了簡(jiǎn)單,就使用刪除或增加 -encrypt 這個(gè),實(shí)際情況下可以使用復(fù)雜的加解密規(guī)則

           

          0x01: 基本思路介紹

          RequestBodyAdvice:在 sping 4.2 新加入的一個(gè)接口,它可以使用在 @RequestBody 或 HttpEntity 修改的參數(shù)之前進(jìn)行參數(shù)的處理,比如進(jìn)行參數(shù)的解密

          ResponseBodyAdvice:在 spring 4.1 新加入的一個(gè)接口,在消息體被 HttpMessageConverter 寫入之前允許 Controller 中 @ResponseBody 修飾的方法或 ResponseEntity 調(diào)整響應(yīng)中的內(nèi)容,比如進(jìn)行相應(yīng)的加密

           

          0x02: 功能實(shí)現(xiàn)步驟

          1. 編寫加密注解類(Encrypt)

          @Target({ElementType.PARAMETERElementType.METHOD})  
          @Retention(RetentionPolicy.RUNTIME)  
          @Documented  
          public @interface Encrypt {  

          }  

           2. 編寫RequestBodyAdvice接口實(shí)現(xiàn)類,實(shí)現(xiàn)數(shù)據(jù)的解密操作

          @Slf4j  
          @RestControllerAdvice  
          public class ParamEncryptRequestBodyAdvice implements RequestBodyAdvice {  

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

              @Override  
              public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {  
                  return o;  
              }  

              @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 {  
                          log.info("此處進(jìn)行解密數(shù)據(jù)");  
                          return new ByteArrayInputStream(IOUtils.toString(httpInputMessage.getBody()).replace("-encrypt""").getBytes(StandardCharsets.UTF_8));  
                      }  

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

              @Override  
              public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {  
                  return o;  
              }  
          }  

          3. 編寫ResponseBodyAdvice接口實(shí)現(xiàn)類,實(shí)現(xiàn)數(shù)據(jù)的加密操作

          @Slf4j  
          @RestControllerAdvice  
          public class ParamEncryptResponseBodyAdvice implements ResponseBodyAdvice {  

              private final ObjectMapper objectMapper = new ObjectMapper();  

              @Override  
              public boolean supports(MethodParameter returnType, Class converterType) {  
                  return returnType.hasMethodAnnotation(ResponseBody.class);  
              }  

              @Override  
              public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {  
                  log.info("此處進(jìn)行加密數(shù)據(jù)");  
                  if (null != body) {  
                      try {  
                          Map map = objectMapper.readValue(objectMapper.writeValueAsString(body), Map.class);  
                          map.forEach((key, value) -> map.put(key, value + "-encrypt"));  
                          return map;  
                      } catch (IOException e) {  
                          log.error("加密數(shù)據(jù)失敗.", e);  
                      }  
                  }  
                  return body;  
              }  
          }  

          4. 編寫控制層進(jìn)行測(cè)試

          @RestController  
          @RequestMapping("user-info")  
          @Slf4j  
          public class UserInfoController {  

              /** 
               * 添加用戶實(shí)現(xiàn)返回值加密 
               * 
               * @param userInfo 
               * @return 
               */
            
              @PostMapping("add")  
              @Encrypt  
              public UserInfo add(@RequestBody UserInfo userInfo) {  
                  log.info("添加新用戶:[{}]", userInfo);  
                  return userInfo;  
              }  

              /** 
               * 修改實(shí)現(xiàn)獲取的參數(shù)進(jìn)行解密 
               * 
               * @param userInfo 
               * @return 
               */
            
              @PostMapping("update")  
              public UserInfo update(@Encrypt @RequestBody UserInfo userInfo) {  
                  log.info("修改用戶信息:[{}]", userInfo);  
                  return userInfo;  
              }  
          }  

          5. 測(cè)試參數(shù)的解密操作


          可以看到:參數(shù)中的 -encrypt 傳遞后后臺(tái)被后臺(tái)自動(dòng)截取了,這樣就類似于解密操作。

          6. 測(cè)試返回值的加密操作

          可以看到:返回的值后面都有一個(gè) -encrypt, 這樣就實(shí)現(xiàn)了類似于加密操作。

          喜歡,在看


          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久久久久久久久艹 | 在线观看黄色小电影 | 丁香五月色婷中文 | 中文字幕亚洲a√ | 操逼达人|