generated from nemowang/springcloud-dubbo-nacos-example
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RequestHandler.java
190 lines (167 loc) · 6.75 KB
/
RequestHandler.java
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package com.nemo.consumer.handler;
import cn.hutool.core.text.UnicodeUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.nemo.api.enums.ResultEnum;
import com.nemo.api.exception.BusinessException;
import com.nemo.api.service.SecurityService;
import com.nemo.common.util.AESUtil;
import com.nemo.common.util.RSAUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
/**
* @Author Nemo
* @Description 解密request中的数据
* @Date 2020/11/20 9:59
*/
@Slf4j
public class RequestHandler extends HttpServletRequestWrapper {
/**
* 存储body数据的容器
* request中的body只能读取一次,因此定义变量暂存
*/
private byte[] body;
/**
* 处理入参
* 解密
*
* 入参结构:
* bizContent: AES加密后的接口入参密文
* domain: RSA加密后的AES密钥
* appId: appId用于区分系统
*
* @param request request
* @param securityService 非对称加密公私钥管理服务
* @param encryptSwitch 加解密开关
*/
public RequestHandler(HttpServletRequest request, SecurityService securityService, String encryptSwitch) {
super(request);
String contentType = request.getMethod();
if ("GET".equals(contentType)) {
log.info("RequestHandler don't support GET method. RequestHandler不支持get请求");
throw new BusinessException(ResultEnum.REQUEST_ERROR);
}
// 私钥,用来解密
String privateKey = StringUtils.EMPTY;
// 密文(RSA加密)
String encData = StringUtils.EMPTY;
try {
// 将body数据存储起来
String bodyStr = this.getBodyString(request);
log.info("RequestHandler 请求开始解析bodyStr:{}", bodyStr);
// step1. 读取请求数据
JSONObject jsonObject = JSONUtil.parseObj(bodyStr);
// 加密开关关闭时,直接返回
if ("false".equals(encryptSwitch)) {
body = encData.getBytes(Charset.defaultCharset());
return;
}
if (JSONUtil.isNull(jsonObject.get("bizContent"))) {
log.info("RequestHandler 参数不能为空");
throw new BusinessException(ResultEnum.PARAM_EMPTY);
}
encData = jsonObject.getStr("bizContent");
log.info("RequestHandler 加密串encData:{}", encData);
String domain = jsonObject.getStr("domain");
log.info("RequestHandler domain:{}", domain);
if (StringUtils.isEmpty(domain)) {
log.info("RequestHandler 解密失败,domain不能为空。");
throw new BusinessException(ResultEnum.DECRYPT_ERROR);
}
String appId = jsonObject.getStr("appId");
log.info("RequestHandler appId:{}", appId);
if (StringUtils.isEmpty(appId)) {
log.info("RequestHandler 解密失败,appId不能为空");
throw new BusinessException(ResultEnum.APPID_EMPTY);
}
// step2. 获取RSA私钥,解密AES密钥
// 获取RSA私钥
privateKey = securityService.getPrivateKey(appId);
log.info("RequestHandler 获取私钥privateKey:{}", privateKey);
// 解密AES密钥
String decryptDomainKey = RSAUtils.decrypt(domain, privateKey);
log.info("RequestHandler domainkey:{}, encData:{}", decryptDomainKey, encData);
// step3. 使用AES密钥解密数据
// AES使用decryptDomainKey解密encData获取bizContent中的数据
String decryptUnicode = AESUtil.decrypt(encData, decryptDomainKey);
log.info("RequestHandler 解析的得到的数据为:{}", decryptUnicode);
String decrypt = UnicodeUtil.toString(decryptUnicode);
log.info("RequestHandler decryptUnicode转String得到的数据为:{}", decrypt);
// step4. 返回给body
JSONObject result = new JSONObject();
if (StringUtils.isNotBlank(decrypt)) {
result = JSONUtil.parseObj(decrypt);
}
// 把domainkey放到参数中,返回数据加密时使用
result.put("domainKey", decryptDomainKey);
log.info("RequestHandler resultJson={}", JSONUtil.toJsonStr(result));
body = JSONUtil.toJsonStr(result).getBytes();
} catch (BusinessException e) {
log.error("RequestHandler.RequestHandler decrypt error. privateKey:{}, encData:{}", privateKey, encData, e);
// 继续抛出异常,让filter去处理
throw new BusinessException(e.getMessage());
} catch (Exception e) {
log.error("RequestHandler error.", e);
throw new BusinessException(ResultEnum.FAIL);
}
}
/**
* 获取请求body
* @param request
* @return bodyStr
*/
private String getBodyString(HttpServletRequest request) {
try {
return this.inputStream2String(request.getInputStream());
} catch (IOException e) {
log.error("RequestHandler.getBodyString error.", e);
throw new RuntimeException(e);
}
}
/**
* 将inputStream里的数据读取出来并转换成字符串
* @param inputStream
* @return String
*/
private String inputStream2String(InputStream inputStream) {
String content = null;
try {
content = IOUtils.toString(inputStream, "UTF-8");
} catch (IOException e) {
log.error("RequestHandler.inputStream2String error.", e);
}
return content;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}