1. 程式人生 > >Spring 介面資料加解密---全域性加解密篇

Spring 介面資料加解密---全域性加解密篇

Spring 介面資料加解密—全域性加解密篇

  • 資料加密傳輸
  • 加解密處理
  • 自定義message-converters
  • 小結

資料加密傳輸

企業級開發,是缺少不了資料的加密傳輸。如若不是,請自重。微信公共號的開發便提供AES加密處理,提高公共號的安全性。

加解密處理

(一) 請求資料加密演算法加密生成字串,按照MediaType=text/plain請求訪問,伺服器接收到字串,並對字串進行解密。響應結果加密生成字串,並響應。
優勢:隨性。
劣勢:僅能處理字串,字串明文也有被破解風險。且比如RC4演算法加密後生成的位元組轉字串是解密不了的。
(二) 自定義message-converters,訊息轉換器的呼叫完全依照請求的MediaType

資訊(本文詳細介紹,目前restful主流,這裡針對json串處理)。
優勢:僅需實現介面,簡單配置。
劣勢:對同一型別的MediaType都進行加解密操作。
(三) 使用spring提供的介面RequestBodyAdvice和ResponseBodyAdvice對資料加解密。
優勢:可指定介面加解密,無需配置。
劣勢:需要升級spring4.2及以上。
(四) 使用攔截器,進行處理。

自定義message-converters

applicationContext.xml 中配置自定義的訊息轉換器:

<mvc:annotation-driven>
<mvc:message-converters register-defaults="true"> <!-- 配置自定義轉換器com.JsonMessageConverter--> <bean class="com.JsonMessageConverter"> <property name="objectMapper"> <bean class="com.fasterxml.jackson.databind.ObjectMapper"
>
<property name="serializationInclusion"> <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">ALWAYS</value> </property> </bean> </property> <property name="supportedMediaTypes"> <list> <!--自定義轉換器可處理的MediaType 只要是請求頭是這幾種型別便自然被這個轉換器處理--> <value>text/html;charset=UTF-8</value> <value>text/json;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>

實現訊息轉換器com.JsonMessageConverter,這裡是針對json的,所以繼承MappingJackson2HttpMessageConverter。

package com;
public class CustomerJsonMessageConverter extends MappingJackson2HttpMessageConverter {

    //資料讀前
    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        JavaType javaType = this.getJavaType(clazz, (Class) null);

        InputStream is = inputMessage.getBody();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] b = new byte[4096];
        int n = 0;
        while ((n = is.read(b)) > 0) {
            out.write(b, 0, n);
        }
        //解密 解密
        String plainBody = decrypt(out);
        try {
            return this.objectMapper.readValue(new ByteArrayInputStream(plainBody.getBytes()), javaType);
        } catch (IOException ex) {
            throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
        }
    }

    //資料寫後
    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException,
            HttpMessageNotWritableException {
        String plainRspJson = objectMapper.writeValueAsString(object);
        //加密
        outputMessage.getBody().write(encrypt(plainRspJson.getBytes()));
    }
}

@requestBody和@responseBody這兩個註解,對應readInternal(讀前)在這個方法進行解密,然後重寫writeInternal(寫後)在這個方法進行加密輸出。

小結

如上看出加解密處理還是很簡單,但是缺點也是顯而易見的,對同一型別指定的MediaType必須得過加解密方法,當然對應處理策略統一地倒也無可厚非。