springboot全面加密方案
-
最近项目上又出幺蛾子了,甲方要求前端后台全部的数据都需要加密处理,不允许明文。简单的来说,就是传的参数是加密数据,然后接口返回给前端的数据也是加密数据。
-
显示的效果就是比方说,前端传给我的是一个json
{
"data":"8cfd4ebd90359d687b0dd8345fad44ab3405cecd81e9d7e5da5ec994259e171575aa2384a024677276c98db9c13ef66e"
} -
然后我拿到这个数据后解析成原本我的接口的参数,然后传到接口中处理逻辑,然后把返回值也加密,返回给前端的值类似于
{
"result":"6CC375B93947D06ED64E4A0E21227147C0D63EB71BD871EFFAF3A6319A7A6519B55E8919E0B505321230CC0DD951B535F6C8BB42EBFF6DA07B6F7C638658714F59D0522098BA91BB2B51174EF08B9DC99A98D99BD6A31599A995CAB8996EE4C2"
} -
于是就要开始思考如何解决该问题,由于项目里没有统一的格式规范,各种类型层出不穷,比如@RequestBody,或者@RequestParam,各种表单提交或者json提交,然后返回值也是各种各样的。这对于我做全面加密产生了极大的阻碍。
-
正常做首先看网上有没有现成的,但是经过我多次试验,均无法满足我的全部需求,它只能处理json格式的,对于我表单提交的方式那就是一个无能为力
-
然后还有拦截器的方式,本来我是非常看好这个方法,但是拦截器HandlerInterceptor,我实在是无法实现解析后再把值变为表单提交进原来的接口中,如果有大佬实现了,希望能告诉在下,如何实现。
-
同理自定义注解,也是同样的原因,我始终无法实现把解析后的参数转化为表单再重新提交进接口
-
最后我使用过滤器的方式来实现,过滤器,缺失能实现把值转化为表单重新提交进接口
-
而把返回值重新进行加密的方式,我选择使用implements ResponseBodyAdvice,我测试目前基本上返回值都会经过这里,重新进行加密封装后,再返回给前端
-
进入filter后,重新赋值
MyParameterRequestWrapper wrapRequest = new MyParameterRequestWrapper(request, newParams, jsonData);
其中,newParams传的是表单的数据,jsonData传的是json的数据,都是解析出来的数据,然后继续进入下一个过滤
filterChain.doFilter(wrapRequest, servletResponse);
public class MyParameterRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> params;
private String requestBody = null;/** * Constructs a request object wrapping the given request. * * @param request the {@link HttpServletRequest} to be wrapped. * @throws IllegalArgumentException if the request is null */ public MyParameterRequestWrapper(HttpServletRequest request, Map<String, String[]> params, String requestBody) { super(request); this.params = params; this.requestBody = requestBody; } @Override public Map<String, String[]> getParameterMap() { return params; } @Override public Enumeration<String> getParameterNames() { Vector<String> l = new Vector<>(params.keySet()); return l.elements(); } @Override public String[] getParameterValues(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String[]) { return (String[]) v; } else if (v instanceof String) { return new String[]{(String) v}; } else { return new String[]{v.toString()}; } } @Override public String getParameter(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String[]) { String[] strArr = (String[]) v; if (strArr.length > 0) { return strArr[0]; } else { return null; } } else if (v instanceof String) { return (String) v; } else { return v.toString(); } } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new StringReader(requestBody)); } @Override public ServletInputStream getInputStream() throws IOException { ServletRequest request = getRequest(); return new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } private InputStream in = new ByteArrayInputStream( requestBody.getBytes(request.getCharacterEncoding() == null ? "UTF-8" : request.getCharacterEncoding())); // 读取 requestBody 中的数据 @Override public int read() throws IOException { return in.read(); } }; }
}
/**
-
响应加解密拦截器
-
@author lyk
*/
@Component
@ControllerAdvice
public class ResponseHandler implements ResponseBodyAdvice<Object> {// 这里假设你希望只有某些特定的 Controller 或方法走这个处理器
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
//这里可以写一些条件return false,代表不进入返回加密流程
return true;
}/**
-
响应加密
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse serverHttpResponse) {
//这里body就是返回值,对它进行加密即可
String encrypt = encryptEcb(body);JSONObject json = new JSONObject();
json.put("result", encrypt);
return json;
}
}
-
-