欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring MVC 对 ResponseBody返回json数据进行脱敏处理 spring MVCResponseBodySensitive

程序员文章站 2022-04-07 21:18:17
...

为了对springmvc框架中的json请求数据进行可控制的脱敏处理,研究了配置message-converters里面的内容,并通过重写部分方法进行脱敏修改

 

 

  • 配置message-converters 

 

  <mvc:annotation-driven>
        <!-- 处理responseBody 返回结果 -->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <!--<bean class="com.fasterxml.jackson.databind.ObjectMapper">-->
                    <bean class="com.ez.core.servlet.SensitiveObjectMapper">
                        <property name="dateFormat">
                            <bean class="java.text.SimpleDateFormat">
                                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
                            </bean>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

 

  • 需要重写的类有 “com.fasterxml.jackson.databind.ObjectMapper”, “com.fasterxml.jackson.databind.MappingJsonFactory”,“com.fasterxml.jackson.core.json.UTF8JsonGenerator”;

 

package com.ez.core.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DefaultDeserializationContext;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;

/**
 * Created by Administrator on 2018/2/8.
 */
public class SensitiveObjectMapper extends ObjectMapper {

    /**
     * 对弗雷的jsonfactory使用自定义工厂
     */
    public SensitiveObjectMapper() {
        super(new SensitiveJsonFactory(), (DefaultSerializerProvider) null, (DefaultDeserializationContext) null);
    }
}

 

 

 

package com.ez.core.servlet;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.json.UTF8JsonGenerator;
import com.fasterxml.jackson.databind.MappingJsonFactory;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

/**
 * Created by Administrator on 2018/2/8.
 */
public class SensitiveJsonFactory extends MappingJsonFactory {
    public SensitiveJsonFactory() {
        super();
    }

    public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException {
        IOContext ctxt = this._createContext(out, false);
        ctxt.setEncoding(enc);
        if (enc == JsonEncoding.UTF8) {
            return this._createUTF8Generator(this._decorate(out, ctxt), ctxt);
        } else {
            Writer w = this._createWriter(out, enc, ctxt);
            return this._createGenerator(this._decorate(w, ctxt), ctxt);
        }
    }

    /**
     * 主要是重写该方法,对需要进行脱敏处理的数据,使用 SensitiveUTF8JsonGenerator 处理,
     * 不需要脱敏的数据,还是按照原来的路径进行处理
     * @param out
     * @param ctxt
     * @return
     * @throws IOException
     */
    protected JsonGenerator _createUTF8Generator(OutputStream out, IOContext ctxt) throws IOException {
        UTF8JsonGenerator gen = null;
        boolean needSensitive = !true;

        if (needSensitive) {
            gen = new SensitiveUTF8JsonGenerator(ctxt, this._generatorFeatures, this._objectCodec, out);
        } else {
            gen = new UTF8JsonGenerator(ctxt, this._generatorFeatures, this._objectCodec, out);
        }

        if (this._characterEscapes != null) {
            gen.setCharacterEscapes(this._characterEscapes);
        }

        SerializableString rootSep = this._rootValueSeparator;
//        if (rootSep != _rootValueSeparator) {
//        if(rootSep != DEFAULT_ROOT_VALUE_SEPARATOR) {
        gen.setRootValueSeparator(rootSep);
//        }

        return gen;
    }


}

 

 最后需要对真正写入流的方法进行重写,通过判断是否需要进行脱敏处理,然后根据具体的脱敏规则进行处理,判断时可能需要通过当前数据的路径进行判断,所以增加了basePath存储先关路径,一般脱敏规则,是将相关数据替换为***

package com.ez.core.servlet;

import com.fasterxml.jackson.core.Base64Variant;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.json.UTF8JsonGenerator;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * Created by Administrator on 2018/2/8.
 */
public class SensitiveUTF8JsonGenerator extends UTF8JsonGenerator {

    private StringBuffer basePath = new StringBuffer();

    //    private String[] path = new String[];
    public SensitiveUTF8JsonGenerator(IOContext ctxt, int features, ObjectCodec codec, OutputStream out) {
        super(ctxt, features, codec, out);
    }

    public SensitiveUTF8JsonGenerator(IOContext ctxt, int features, ObjectCodec codec, OutputStream out, byte[] outputBuffer, int outputOffset, boolean bufferRecyclable) {
        super(ctxt, features, codec, out, outputBuffer, outputOffset, bufferRecyclable);
    }


    private void addPath(SerializableString name) {
        this.basePath.append(".").append(name);
    }

    private void addPath(String name) {
        this.basePath.append(".").append(name);
    }

    private void deleteOnePath() {
        int index = basePath.lastIndexOf(".");
        if (index != -1) {
            basePath.delete(index, basePath.length());
        }

    }

    private void dealRemovePath() {
        deleteOnePath();
    }

    public void writeFieldName(SerializableString name) throws IOException {
        addPath(name);
        super.writeFieldName(name);
    }

    public void writeFieldName(String name) throws IOException {
        addPath(name);
        super.writeFieldName(name);
    }

    public void writeString(String text) throws IOException {
        text = sensitiveTransfer(text);
        super.writeString(text);
    }


    public void writeString(Reader reader, int len) throws IOException {
        super.writeString(reader, len);
        dealRemovePath();
    }

    public void writeString(char[] text, int offset, int len) throws IOException {
        super.writeString(text, offset, len);
        dealRemovePath();
    }

    public void writeRawUTF8String(byte[] text, int offset, int length) throws IOException {
        super.writeRawUTF8String(text, offset, length);
        dealRemovePath();
    }

    public void writeUTF8String(byte[] text, int offset, int len) throws IOException {
        super.writeUTF8String(text, offset, len);
        dealRemovePath();
    }

    public void writeBinary(Base64Variant a, byte[] b, int c, int d) throws IOException, JsonGenerationException {
        super.writeBinary(a, b, c, d);
        dealRemovePath();
    }

    public int writeBinary(Base64Variant a, InputStream b, int c) throws IOException, JsonGenerationException {
        int ret = super.writeBinary(a, b, c);
        dealRemovePath();
        return ret;
    }


    public void writeNumber(short s) throws IOException {
        super.writeNumber(s);
        sensitiveTransfer(s);
    }

    private void sensitiveTransfer(short s) {
        sensitiveTransfer(s);
    }


    public void writeNumber(int i) throws IOException {
        super.writeNumber(i);
        sensitiveTransfer(i);
    }

    private void sensitiveTransfer(int i) {
        dealRemovePath();
    }

    public void writeNumber(long l) throws IOException {
        super.writeNumber(l);
        sensitiveTransfer(l);
    }

    private void sensitiveTransfer(long l) {
        dealRemovePath();
    }


    public void writeNumber(BigInteger value) throws IOException {
        super.writeNumber(value);
        sensitiveTransfer(value);
    }

    private void sensitiveTransfer(BigInteger value) {
        dealRemovePath();
    }

    public void writeNumber(double d) throws IOException {
        super.writeNumber(d);
        sensitiveTransfer(d);
    }

    private void sensitiveTransfer(double d) {
        dealRemovePath();
    }


    public void writeNumber(float f) throws IOException {
        super.writeNumber(f);
        sensitiveTransfer(f);
    }

    private void sensitiveTransfer(float f) {
        dealRemovePath();
    }

    public void writeNumber(BigDecimal value) throws IOException {
        super.writeNumber(value);
        sensitiveTransfer(value);
    }

    private void sensitiveTransfer(BigDecimal value) {
        dealRemovePath();
    }

    public void writeNumber(String encodedValue) throws IOException {
        encodedValue = sensitiveTransfer(encodedValue);
        super.writeNumber(encodedValue);
    }

    private String sensitiveTransfer(String encodedValue) {
        /**
         * 判断是否需要进行脱敏
         * 根据 basePath 和脱敏规则;
         */

//        String ret = encodedValue ;
        String ret = encodedValue + "脱敏";

//        System.out.println("basePath: " + basePath);
//        try {
//            System.out.println(new String(this._outputBuffer, "UTF-8"));
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
        dealRemovePath();
        return ret;
    }


    public void writeBoolean(boolean state) throws IOException {
        super.writeBoolean(state);
        sensitiveTransfer(state);
    }

    private void sensitiveTransfer(boolean state) {
        /**
         * 判断是否需要进行脱敏
         * 根据 basePath 和脱敏规则;
         */
        dealRemovePath();
    }

    public void writeNull() throws IOException {
        super.writeNull();
        dealRemovePath();
    }


}