一、过滤器中对指定接口进行加密

去除指定接口验证的话,将会是对所有接口请求参数进行解密。

1、找到项目中的过滤器:RepeatableFilter

过滤器中的RepeatedlyRequestWrapper对POST请求参数数据允许可重复读取

2、下面对 RepeatedlyRequestWrapper进行改造(数据进行解密)或者自行创建一个新的xxxxRequestWrapper类替换掉RepeatableFilter中的RepeatedlyRequestWrapper

可添加请求头

/**
 * 构建可重复读取inputStream的request
 * 
 * @author ruoyi
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
    private static final Logger log = LoggerFactory.getLogger(RepeatedlyRequestWrapper.class);

    // 重新赋值的body数据
    private String bodyJsonStr;

    // 重新赋值的请求头
    private Map<String, String> headerMap = new HashMap<>();

    //接口请求参数加密白名单
    public static List<String> encryptApi;

    static {//请求参数需加密的接口
        List<String> list = new ArrayList<String>();
        list.add("xxxxx/xxxxx/xxxxx");
        list.add("xxxxx/xxxxx/xxxxx");

        encryptApi = list;
    }

    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
    {
        super(request);
        request.setCharacterEncoding(Constants.UTF8);
        response.setCharacterEncoding(Constants.UTF8);

        //数据进行解密
        String shuju = preamerJiemi(request);

        this.bodyJsonStr = shuju;
    }

    //参数解密
    public String preamerJiemi(HttpServletRequest request){

        //获取请求路径(接口)
        StringBuffer url = request.getRequestURL();
        System.out.println(url);

        String shuju = null;
        if(getBoolenStatus(url.toString())){//验证接口是否需要对请求参数解密
            //获取请求参数
            String requestData = readBodyBytes(request);
            JSONObject jsonData = JSONObject.parseObject(requestData);
            String data = jsonData.getString("xxxxx");//获取加密数据

            if(StringUtils.isBlank(data)){
                log.error("请求参数xxxxx加密数据不存在");
                throw new ServiceException("请求参数xxxxx不存在");
            }

            try {
                //对data数据进行解密(解密工具类请自行替换,需与客户端加密方式保持一致)
                shuju = AES128Util.decryptAES(data,AES128Util.keyIvJson);
                
                //请求头中添加数据(无此需求可去除)
                if(StringUtils.isBlank(getHeader("xxxxx"))){
                    //请求头中添加数据
                    addHeader("xxxxx", "xxxxx");
                }
            }catch (Exception e){
                log.error("解密失败:{}",e.getMessage());
                throw new ServiceException("解密失败,请联系客服");
            }
        }else{
            shuju = readBodyBytes(request);
        }

        return shuju;
    }

    //验证请求接口是否加入请求参数白名单
    public boolean getBoolenStatus(String requestURL){
        if(encryptApi != null && encryptApi.size() > 0){
            for(String list:encryptApi){
                if(requestURL.contains(list)){
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if(StringUtils.isEmpty(bodyJsonStr)) {
            bodyJsonStr = "";
        }
        // 必须指定utf-8编码,否则json请求数据中如果包含中文,会出现异常
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bodyJsonStr.getBytes("utf-8"));
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener) {
            }
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public String getBodyJsonStr() {
        return bodyJsonStr;
    }

    public void setBodyJsonStr(String bodyJsonStr) {
        this.bodyJsonStr = bodyJsonStr;
    }


    /**
     * add a header with given name and value
     *
     * @param name
     * @param value
     */
    public void addHeader(String name, String value) {
        headerMap.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        log.info("getHeader --->{}",name);
        String headerValue = super.getHeader(name);
        if (headerMap.containsKey(name)) {
            headerValue = headerMap.get(name);
        }
        return headerValue;
    }

    /**
     * get the Header names
     */
    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        for (String name : headerMap.keySet()) {
            names.add(name);
        }
        return Collections.enumeration(names);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        List<String> values = Collections.list(super.getHeaders(name));
        if (headerMap.containsKey(name)) {
            values = Arrays.asList(headerMap.get(name));
        }
        return Collections.enumeration(values);
    }

    //获取请求体中的JSON格式参数
    private String readBodyBytes(HttpServletRequest request) {

        String bodyContent = null;
        try {
            byte[] bodyBytes = readInputBody(request.getInputStream());
            bodyContent = new String(bodyBytes, Constants.UTF8);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return bodyContent;
    }

    private byte[] readInputBody(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) > -1) {
            byteArrayOutputStream.write(buffer, 0, len);
        }
        byteArrayOutputStream.flush();
        return byteArrayOutputStream.toByteArray();
    }
}

响应信息进行拦截并加密

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.xdsjzs.common.filter.RepeatedlyRequestWrapper;
import com.xdsjzs.common.utils.StringUtils;
import com.xdsjzs.common.utils.sign.AES128Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;


/**
 * 响应信息拦截器
 */
@RestControllerAdvice
public class ResponseResultAdvice implements ResponseBodyAdvice<Object> {

    private static final Logger log = LoggerFactory.getLogger(RepeatedlyRequestWrapper.class);

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;//此信息改为false的话 将不对响应信息进行拦截
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //return null;
        // 可对响应报文做一些操作
        Object jsonObject = jiami(body,request);
        return jsonObject;
    }

    /**
     * 响应信息进行加密
     * @param body
     * @param requestWrapper
     * @return
     */
    public static JSONObject jiami(Object body,ServerHttpRequest requestWrapper){

        JSONObject jsonDataRe = JSONObject.parseObject(JSONObject.toJSONString(body));
        jsonDataRe.put("status",0);//默认不加密

        String url = requestWrapper.getURI().getPath();

        //验证接口是否需要对请求参数解密
        if(AES128Util.getBoolenStatus(url)) {
            String jsonData = jsonDataRe.getString("data");
            if(StringUtils.isNotBlank(jsonData)){
                //将唯一码提取出来反转奇偶位置的字符串
                JSONObject jsonObject = AES128Util.fzjo(AES128Util.uniqueCode);
                //进行加密
                String data = AES128Util.encryptAES(jsonData,jsonObject);
                jsonDataRe.put("status",1);//加密
                jsonDataRe.put("data",data);
            }
        }
        return jsonDataRe;
    }
}

到此就结束了。

以下为参考文章:

HttpServletRequest修改header值_httpservletrequest 设置header_thulium_的博客-CSDN博客

重写Request,修改Request中的Body内容 - 简书

前后端分离数据传输加解密方案(建议方案二)_前后端分离密码加密解决方案_zengliangxi的博客-CSDN博客

响应拦截参考文章:

Spring Boot响应结果返回拦截_springboot拦截返回数据_InterestAndFun的博客-CSDN博客 

 获取所有请求参数(Map的形式返回):

	public static Map getRequestParamMap(HttpServletRequest request)
	{
		Map map = new HashMap(); 
		//得到枚举类型的参数名称,参数名称若有重复的只能得到第一个 
		Enumeration enums = request.getParameterNames(); 
	    while (enums.hasMoreElements()) 
	    { 
		    String paramName = (String) enums.nextElement(); 
		    String paramValue = request.getParameter(paramName); 
	
		    //形成键值对应的map 
		    map.put(paramName, paramValue); 
	    }
		return map;
	}

Logo

快速构建 Web 应用程序

更多推荐