Springboot请求参数解密

新建一个 HttpServletRequestWrapper 实现类,在Filter 中使用该类包装原request

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.test.base.config.SecretConfig;
import com.test.common.constant.CommonConstant;
import com.test.common.exception.IchibanShoException;
import com.test.common.servlet.CommonServletInputStream;
import lombok.extern.slf4j.Slf4j;
 
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
 
@Slf4j
public class DecryptHttpServletRequest extends HttpServletRequestWrapper {
    private byte[] body;
    private static SecretConfig secretConfig;
    private final Map<String, String[]> parameterMap = new HashMap<>();
 
    public DecryptHttpServletRequest (HttpServletRequest request) {
        super(request);
        if (Objects.isNull(secretConfig)) {
            secretConfig = SpringUtil.getBean(SecretConfig.class);
        }
        if (MapUtil.isNotEmpty(request.getParameterMap())) {
            parameterMap.putAll(request.getParameterMap());
        }
        decryptSecretParam();
        decryptPostBody(request);
    }
 
    private void decryptSecretParam() {
        String secretParam = getParameter("secretParam");
        MapUtil.removeAny(parameterMap, "secretParam");
        if (StrUtil.isNotBlank(secretParam) && Objects.nonNull(secretConfig)) {
            log.info(">>>>>>>>>>> 解密 secretParam 开始 <<<<<<<<<<<<<<<<<<");
            log.info("原始secretParam: {}", secretParam);
            secretParam = URLDecoder.decode(secretParam, StandardCharsets.UTF_8);
            log.info("URLDecoder后secretParam: {}", secretParam);
            String privateKey = secretConfig.getPrivateKey();
            String publicKey = secretConfig.getPublicKey();
            if (CharSequenceUtil.isNotBlank(privateKey)) {
                RSA rsa = SecureUtil.rsa(privateKey, publicKey);
                rsa.setDecryptBlockSize(CommonConstant.RSA_DECRYPT_BLOCK_SIZE);//hutool RSA解密默认128
                String decryptData = rsa.decryptStr(secretParam, KeyType.PrivateKey);
                log.info("RSA解码后secretParam: {}", decryptData);
                decryptData = URLDecoder.decode(decryptData, StandardCharsets.UTF_8);
                log.info("URLDecoder后decryptData: {}", decryptData);
                if (CharSequenceUtil.isNotBlank(decryptData)) {
                    decryptData = StrUtil.removePrefix(decryptData, "\"");
                    decryptData = StrUtil.removeSuffix(decryptData, "\"");
                    log.info("去除首尾双引号后decryptData: {}", decryptData);
                    List<String> params = StrUtil.split(decryptData, "&");
                    for (String param : params) {
                        List<String> paramArr = StrUtil.splitTrim(param, "=");
                        if (CollUtil.isNotEmpty(paramArr) && paramArr.size() == 2) {
                            setParameter(paramArr.get(0), paramArr.get(1));
                        }
                    }
                }
            }
            log.info(">>>>>>>>>>> 解密 secretParam 结束 <<<<<<<<<<<<<<<<<<");
        }
    }
 
    private void decryptPostBody(HttpServletRequest request) {
        try {
            InputStream inputStream = request.getInputStream();
            String bodyStr = IoUtil.read(new InputStreamReader(inputStream));
            if (JSONUtil.isTypeJSON(bodyStr)) {
                JSONObject jsonObject = JSONUtil.parseObj(bodyStr);
                if (jsonObject.containsKey("secretData")) {
                    bodyStr = jsonObject.getStr("secretData");
                }
            }
            if (!JSONUtil.isTypeJSON(bodyStr) && CharSequenceUtil.isNotBlank(bodyStr) && Objects.nonNull(secretConfig)) {
                log.info(">>>>>>>>>>> 解密 secretData 开始 <<<<<<<<<<<<<<<<<<");
                log.info("原始secretData: {}", bodyStr);
                String privateKey = secretConfig.getPrivateKey();
                String publicKey = secretConfig.getPublicKey();
                if (CharSequenceUtil.isNotBlank(privateKey)) {
                    RSA rsa = SecureUtil.rsa(privateKey, publicKey);
                    rsa.setDecryptBlockSize(CommonConstant.RSA_DECRYPT_BLOCK_SIZE);
                    String decryptData = rsa.decryptStr(bodyStr, KeyType.PrivateKey);
                    log.info("RSA解码后secretData: {}", decryptData);
                    decryptData = URLDecoder.decode(decryptData, StandardCharsets.UTF_8);
                    log.info("URLDecoder后secretData: {}", decryptData);
                    if (CharSequenceUtil.isNotBlank(decryptData)) {
                        body = CharSequenceUtil.bytes(decryptData);
                    } else {
                        throw new IchibanShoException("无效的请求参数");
                    }
                } else {
                    body = CharSequenceUtil.bytes(bodyStr);
                }
                log.info(">>>>>>>>>>> 解密 secretData 结束 <<<<<<<<<<<<<<<<<<");
            } else {
                body = CharSequenceUtil.bytes(bodyStr);
            }
        } catch (Exception e) {
            log.error("解密失败", e);
        }
    }
 
    public void setParameter(String name, String value) {
        parameterMap.put(name, new String[] { value });
    }
 
    @Override
    public String getParameter(String name) {
        String[] values = parameterMap.get(name);
        if (ArrayUtil.isNotEmpty(values)) {
            return values[0];
        }
        return StrUtil.EMPTY;
    }
 
    @Override
    public Map<String, String[]> getParameterMap() {
        return parameterMap;
    }
 
    @Override
    public Enumeration<String> getParameterNames() {
        Vector<String> parameterNames = new Vector<>(parameterMap.keySet());
        return parameterNames.elements();
    }
 
    @Override
    public String[] getParameterValues(String name) {
        return parameterMap.get(name);
    }
 
    @Override
    public ServletRequest getRequest() {
        return super.getRequest();
    }
 
    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(body)));
    }
 
    @Override
    public ServletInputStream getInputStream() {
        return new CommonServletInputStream(new ByteArrayInputStream(body));
    }
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
 
public class CommonServletInputStream extends ServletInputStream {
    private final ByteArrayInputStream inputStream;
 
    public CommonServletInputStream(ByteArrayInputStream inputStream) {
        this.inputStream = inputStream;
    }
 
    @Override
    public boolean isFinished() {
        return inputStream.available() == 0;
    }
 
    @Override
    public boolean isReady() {
        return true;
    }
 
    @Override
    public void setReadListener(ReadListener readListener) {
 
    }
 
    @Override
    public int read() {
        return inputStream.read();
    }
 
    @Override
    public void close() throws IOException {
        inputStream.close();
    }
}

  在filter中:filterChain.doFilter(new DecryptHttpServletRequest(request), response);

posted @   浪天涯&*  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示