1.使用 Filter 将request数据解密
1.1 Filter 代码
@Component
public class DecryptFilter extends OncePerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(DecryptFilter.class);
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
boolean shouldEncrypt = false;
String version = request.getHeader(AuthConstants.VERSION_CODE);
String contentType = request.getContentType();
String requestBody = null;
if (check(version, request.getMethod()) && StringUtils.isNotEmpty(contentType)) {
if (org.springframework.util.StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
shouldEncrypt = true;
requestBody = convertFormToString(request);
} else if (org.springframework.util.StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_JSON_VALUE)) {
shouldEncrypt = true;
requestBody = convertInputStreamToString(request.getInputStream());
}
}
if (shouldEncrypt) {
Map<String, Object> parameterMap = new LinkedHashMap<>();
DecryptHttpWrapper wrapper = new DecryptHttpWrapper(request, objectMapper.readValue(requestBody, parameterMap.getClass()));
filterChain.doFilter(wrapper, response);
} else {
filterChain.doFilter(request, response);
}
}
/**
* 判断是否需要加解密
**/
public static boolean check(final String version, final String method) {
boolean shouldEncrypt = false;
try {
if (StringUtils.isNotEmpty(version) && StringUtils.isNotEmpty(method)) {
String checkMethod = method.toUpperCase();
int versionInt = Integer.parseInt(version);
if (versionInt >= AndroidVersion.DECRYPT_VERSION && ("POST".equals(checkMethod) || "PUT".equals(checkMethod))) {
shouldEncrypt = true;
}
}
} catch (Exception e) {
logger.error(e.getMessage());
shouldEncrypt = false;
}
return shouldEncrypt;
}
/**
* 判断是否需要加解密
**/
public static boolean check(final String version) {
boolean shouldEncrypt = false;
try {
if (StringUtils.isNotEmpty(version)) {
int versionInt = Integer.parseInt(version);
if (versionInt >= AndroidVersion.DECRYPT_VERSION) {
shouldEncrypt = true;
}
}
} catch (Exception e) {
logger.error(e.getMessage());
shouldEncrypt = false;
}
return shouldEncrypt;
}
private String convertFormToString(HttpServletRequest request) {
String data = request.getParameter(AuthConstants.SECURE_DATA);
try {
return SecureHelper.decryptString(data);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private String convertInputStreamToString(InputStream inputStream) throws IOException {
Map<String, String> map = new LinkedHashMap<>();
String data = StreamUtils.copyToString(inputStream, Charset.forName("UTF-8"));
map = objectMapper.readValue(data, map.getClass());
return SecureHelper.decryptString(map.get(AuthConstants.SECURE_DATA));
}
}
1.2 注册Filter
@Bean
public FilterRegistrationBean customEncryptFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new DecryptFilter());
registration.addUrlPatterns("/**");
registration.setName(DecryptFilter.class.getName());
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
1.3 自定义的 RequestWrapper
public class DecryptHttpWrapper extends HttpServletRequestWrapper {
// todo: 还是使用Object比较好,防止出现复杂的数据类型
private Map<String, String[]> parameterMap = new LinkedHashMap<>();
public DecryptHttpWrapper(HttpServletRequest request, Map<String, Object> parameterMap) {
super(request);
parameterMap.forEach((key, value) -> {
if (value != null) {
this.parameterMap.put(key, new String[]{value.toString()});
}
});
}
@Override
public Enumeration<String> getParameterNames() {
Vector<String> vector = new Vector<String>(parameterMap.keySet());
return vector.elements();
}
@Override
public String getParameter(String name) {
String[] results = parameterMap.get(name);
if (results != null && results.length > 0) {
return results[0];
} else {
return null;
}
}
@Override
public String[] getParameterValues(String name) {
return parameterMap.get(name);
}
@Override
public Map<String, String[]> getParameterMap() {
return parameterMap;
}
public void setParameterMap(Map<String, String[]> parameterMap) {
this.parameterMap = parameterMap;
}
}
2.使用 ControllerAdvice 将response数据加密
2.1 代码
@ControllerAdvice
public class DecryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {
private final Logger logger = LoggerFactory.getLogger(DecryptResponseBodyAdvice.class);
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object obj, MethodParameter methodParameter,
MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
if (serverHttpRequest.getHeaders() != null
&& serverHttpRequest.getHeaders().size() > 0
&& serverHttpRequest.getHeaders().get(AuthConstants.VERSION_CODE) != null
&& serverHttpRequest.getHeaders().get(AuthConstants.VERSION_CODE).size() > 0) {
try {
boolean shouldEncrypt = DecryptFilter.check(serverHttpRequest.getHeaders().get(AuthConstants.VERSION_CODE).get(0));
if (shouldEncrypt) {
return new Result() {{
setData(SecureHelper.encryString(objectMapper.writeValueAsString(obj)));
}};
}
} catch (Exception e) {
logger.error(e.getMessage());
return obj;
}
}
return obj;
}
private static class Result {
@JsonProperty(AuthConstants.SECURE_DATA)
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
}