1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 8652字,需瀏覽 18分鐘

         ·

        2021-05-24 21:48

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

         

        需求:

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

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

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

                   加密:對返回的值中增加 -encrypt 值

                   解密:對傳入的值中刪除 -encrypt 值

        注:

        • @Encrypt 為自定義的一個注解。

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

         

        0x01: 基本思路介紹

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

        ResponseBodyAdvice:在 spring 4.1 新加入的一個接口,在消息體被 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)行測試

        @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. 測試參數(shù)的解密操作


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

        6. 測試返回值的加密操作

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

        喜歡,在看


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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产棈品久久嫩一区 | 搡的我好爽 | 国产偷情自拍视频 | 99产精品成人啪免费网站 | 国产性生活 | 久久六 | 激情深爱五月天 | 色七七久久影院 | 老外操逼视频 | 国产精视频 |