public class ApiSignFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 读取header内容,app_key,签名等内容
String appKey = httpServletRequest.getHeader(APP_KEY);
String sign = httpServletRequest.getHeader(AUTHORIZATION_KEY);
String nonceStr = httpServletRequest.getHeader(NONCE_STR_KEY);
String timestamp = httpServletRequest.getHeader(TIMESTAMP_KEY);
// 缺少header,直接返回错误
if (StringUtils.isBlank(appKey) || StringUtils.isBlank(sign)) {
noOkResp((HttpServletResponse) response, HttpStatus.UNAUTHORIZED);
return;
}
// 读取body
String body = null;
if (httpServletRequest.getContentLength() > 0) {
body = new String(IOUtils.toByteArray(httpServletRequest.getInputStream()), request.getCharacterEncoding());
}
// 根据规则生成签名
String verifySign = generateSign(httpServletRequest.getRequestURL().toString(), body, nonceStr, timestamp);
// 校验签名,校验失败直接返回
if (!StringUtils.equals(sign, verifySign)) {
noOkResp((HttpServletResponse) response, HttpStatus.UNAUTHORIZED);
return;
}
// 解密request body
String postRequestBody = null;
if (StringUtils.isNotBlank(body)) {
JSONObject bodyMap = JSON.parseObject(body);
postRequestBody = clientHelper.decryptBody((String) bodyMap.get(ENCRYPT_BODY_KEY));
}
// 构造新的request和response,继续执行请求
AuthHttpServletRequestWrapper requestWrapper = new AuthHttpServletRequestWrapper(httpServletRequest, postRequestBody);
AuthHttpServletResponseWrapper responseWrapper = new AuthHttpServletResponseWrapper((HttpServletResponse) response);
chain.doFilter(requestWrapper, responseWrapper);
// 请求失败处理
if (responseWrapper.getStatus() != HttpStatus.OK.value()) {
response.getOutputStream().write(responseWrapper.getResponseData());
response.getOutputStream().flush();
return;
}
// 读取body并加密
String respBody = new String(responseWrapper.getResponseData(), responseWrapper.getCharacterEncoding());
String encryptRespBody = clientHelper.encryptBody(respBody);
Map<String, String> encryptBodyMap = new HashMap<>();
encryptBodyMap.put(ENCRYPT_BODY_KEY, encryptRespBody);
String postBody = JSON.toJSONString(encryptBodyMap);
// 生成签名并写入header
nonceStr = UUID.randomUUID().toString();
long respTs = System.currentTimeMillis();
String responseSign = generateSign(requestWrapper.getRequestURL().toString(), postBody, nonceStr, respTs);
((HttpServletResponse) response).addHeader(NONCE_STR_KEY, nonceStr);
((HttpServletResponse) response).addHeader(TIMESTAMP_KEY, String.valueOf(respTs));
((HttpServletResponse) response).addHeader(AUTHORIZATION_KEY, responseSign);
// 写入加密后的reseponse body
response.getWriter().write(postBody);
response.getWriter().flush();
}