In development, we will encounter requirements for encrypted transmission of data transmitted by http. We can rewrite the MappingJackson2HttpMessageConverter class of spring mvc to support encryption and decryption. code show as below:
package com.hzwei.spring.messageconvert.ext; import java.io. *; import java.lang.reflect.Type; import org.springframework.http.*; import org.springframework.http.converter*; import org.springframework.http.converter.json.*; import org.springframework.util.TypeUtils; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.jsecode.platform.util.EncryptDecrypt; /** * Extend the MappingJackson2HttpMessageConverter class to add decryption/encryption support for messages (support spring-web-4.3.x) */ public class EncryptMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter { private static final MediaType TEXT_EVENT_STREAM = new MediaType("text", "event-stream"); private PrettyPrinter ssePrettyPrinter; private boolean needEncryptOutputMessage = false; private boolean needDecryptInputMessage = false; protected void init(ObjectMapper objectMapper){ super.init(objectMapper); DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter(); prettyPrinter.indentObjectsWith(new DefaultIndenter(" ", "\ndata:")); this.ssePrettyPrinter = prettyPrinter; } public boolean isNeedEncryptOutputMessage(){ return needEncryptOutputMessage; } public void setNeedEncryptOutputMessage(boolean needEncryptOutputMessage){ this.needEncryptOutputMessage = needEncryptOutputMessage; } public boolean isNeedDecryptInputMessage(){ return needDecryptInputMessage; } public void setNeedDecryptInputMessage(boolean needDecryptInputMessage){ this.needDecryptInputMessage = needDecryptInputMessage; } @Override protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException{ JavaType javaType = getJavaType(clazz, null); return readJavaType(javaType, inputMessage); } public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException{ JavaType javaType = getJavaType(type, contextClass); return readJavaType(javaType, inputMessage); } private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage){ try{ if(inputMessage instanceof MappingJacksonInputMessage){ Class<?> deserializationView = ((MappingJacksonInputMessage)inputMessage).getDeserializationView(); if(deserializationView != null){ return this.objectMapper.readerWithView(deserializationView) .forType(javaType) .readValue(getInputStreamData(inputMessage.getBody())); } } return this.objectMapper.readValue(getInputStreamData(inputMessage.getBody()), javaType); }catch(JsonProcessingException ex){ throw new HttpMessageNotReadableException("JSON parse error: " + ex.getOriginalMessage(), ex); }catch(IOException ex){ throw new HttpMessageNotReadableException("I/O error while reading input message", ex); } } private byte[] getInputStreamData(InputStream in) throws IOException{ ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; int offset = 0; while((offset = in.read(buff)) > 0){ swapStream.write(buff, 0, offset); } byte[] bytes = swapStream.toByteArray(); if(needDecryptInputMessage){ // Decrypt bytes bytes = EncryptDecrypt.AESFastDecrypt2(bytes); //TODO replace your decryption algorithm here } return bytes; } @Override protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException{ if(needEncryptOutputMessage){ writeInternalEncrypt(object, type, outputMessage); }else{ super.writeInternal(object, type, outputMessage); } } // Serialize the return value and encrypt it with AES protected void writeInternalEncrypt(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException{ MediaType contentType = outputMessage.getHeaders().getContentType(); JsonEncoding encoding = getJsonEncoding(contentType); JsonFactory factory = this.getObjectMapper().getFactory(); ByteArrayBuilder bb = new ByteArrayBuilder(factory._getBufferRecycler()); JsonGenerator generator = factory.createGenerator(bb, encoding); writeToJsonGenerator(object, type, generator, contentType); try{ //TODO replace your own encryption algorithm here byte[] byteData = EncryptDecrypt.AESFastEncrypt(bb.toByteArray()); outputMessage.getBody().write(byteData); }catch(Exception ex){ throw new HttpMessageNotWritableException("Could not encrypt and write message: " + ex.getMessage(), ex); } } // The serialization method to keep the original taste of MappingJackson2HttpMessageConverter protected void writeToJsonGenerator(Object object, Type type, JsonGenerator generator, MediaType contentType) throws IOException, HttpMessageNotWritableException{ try{ writePrefix(generator, object); Class<?> serializationView = null; FilterProvider filters = null; Object value = object; JavaType javaType = null; if(object instanceof MappingJacksonValue){ MappingJacksonValue container = (MappingJacksonValue)object; value = container.getValue(); serializationView = container.getSerializationView(); filters = container.getFilters(); } if(type != null && value != null && TypeUtils.isAssignable(type, value.getClass())){ javaType = getJavaType(type, null); } ObjectWriter objectWriter; if(serializationView != null){ objectWriter = this.objectMapper.writerWithView(serializationView); }else if(filters != null){ objectWriter = this.objectMapper.writer(filters); }else{ objectWriter = this.objectMapper.writer(); } if(javaType != null && javaType.isContainerType()){ objectWriter = objectWriter.forType(javaType); } SerializationConfig config = objectWriter.getConfig(); if(contentType != null && contentType.isCompatibleWith(TEXT_EVENT_STREAM) && config.isEnabled(SerializationFeature.INDENT_OUTPUT)){ objectWriter = objectWriter.with(this.ssePrettyPrinter); } objectWriter.writeValue(generator, value); writeSuffix(generator, object); generator.flush(); }catch(JsonProcessingException ex){ throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getOriginalMessage(), ex); } } }
In the spring mvc project, replace MappingJackson2HttpMessageConverter with EncryptMappingJackson2HttpMessageConverter