实现
过滤器
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 @Slf4j public class SignFilter implements Filter { @Override public void init (FilterConfig filterConfig) throws ServletException { log.info("SignFilter init." ); } @Override public void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { log.info("SignFilter doFilter." ); HttpServletRequest request = (HttpServletRequest) servletRequest; RequestWrapper requestWrapper = new RequestWrapper(request); SortedMap<String, String> sortedMap = RequestUtils.getAllParams(requestWrapper); if (SignUtils.verifySign(sortedMap)) { log.info("验签通过, path: [{}], params: [{}]" , request.getServletPath(), sortedMap.toString()); filterChain.doFilter(requestWrapper, servletResponse); } else { log.error("验签失败, path: [{}], params: [{}]" , request.getServletPath(), sortedMap.toString()); } } @Override public void destroy () { log.info("SignFilter destroy." ); } }
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 public class RequestWrapper extends HttpServletRequestWrapper { private byte [] buffer; public RequestWrapper (HttpServletRequest request) throws IOException { super (request); InputStream is = request.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte buff[] = new byte [1024 ]; int read; while ((read = is.read(buff)) > 0 ) { baos.write(buff, 0 , read); } this .buffer = baos.toByteArray(); } @Override public ServletInputStream getInputStream () { final ByteArrayInputStream bais = new ByteArrayInputStream(buffer); return new ServletInputStream() { @Override public boolean isFinished () { return false ; } @Override public boolean isReady () { return false ; } @Override public void setReadListener (ReadListener readListener) { } @Override public int read () { return bais.read(); } }; } @Override public BufferedReader getReader () throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } }
过滤器配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Configuration public class FilterConfig { @Bean public FilterRegistrationBean filterRegistration () { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new SignFilter()); registration.addUrlPatterns("/*" ); registration.setName("SignFilter" ); registration.setOrder(1 ); return registration; } }
提取请求参数
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 public class RequestUtils { public static Map<String, String> getUrlParams (HttpServletRequest request) { String param = "" ; if (Objects.isNull(request.getQueryString())) { return Collections.EMPTY_MAP; } try { param = URLDecoder.decode(request.getQueryString(), "utf-8" ); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Map<String, String> result = new HashMap<>(16 ); String[] params = param.split("&" ); for (String s : params) { int index = s.indexOf("=" ); result.put(s.substring(0 , index), s.substring(index + 1 )); } return result; } public static Map<String, String> getBodyParams (HttpServletRequest request) throws IOException { String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Map<String, String> map = new Gson().fromJson(body, new TypeToken<HashMap<String, String>>() {}.getType()); return map; } public static SortedMap<String, String> getAllParams (HttpServletRequest request) throws IOException { SortedMap<String, String> sortedParams = new TreeMap<>(); Map<String, String> urlParams = getUrlParams(request); for (Map.Entry entry : urlParams.entrySet()) { sortedParams.put((String) entry.getKey(), (String) entry.getValue()); } if (!HttpMethod.GET.name().equals(request.getMethod())) { Map<String, String> bodyParams = getBodyParams(request); if (null != bodyParams) { for (Map.Entry entry : bodyParams.entrySet()) { sortedParams.put((String) entry.getKey(), (String) entry.getValue()); } } } return sortedParams; } }
验签工具
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 @Slf4j public class SignUtils { public static final String appKey = "wx3f2f5354f615c637" ; public static String getParamsSign (Map<String, String> sortedMap) { sortedMap.remove("sign" ); sortedMap.put("appKey" , appKey); String paramsJsonStr = GsonUtils.toJson(sortedMap); String md5 = DigestUtils.md5DigestAsHex(paramsJsonStr.getBytes()).toUpperCase(); log.info("加签参数: {}, MD5: {}" , paramsJsonStr, md5); return md5; } public static boolean verifySign (Map<String, String> sortedMap) { String inTimeStamp = sortedMap.getOrDefault("ts" , "0" ); LocalDateTime inTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(inTimeStamp)), ZoneOffset.ofHours(8 )); Duration duration = Duration.between(inTime, LocalDateTime.now()); long seconds = duration.get(SECONDS); System.out.println("seconds: " + seconds); if (seconds > 60 ) { System.out.println("请求超时" ); return Boolean.FALSE; } String urlSign = Objects.nonNull(sortedMap.get("sign" ))?sortedMap.get("sign" ):null ; log.info("传递签名: [{}]" , urlSign); if (StringUtils.isBlank(urlSign)) { return false ; } String paramsSign = getParamsSign(sortedMap); log.info("计算签名: [{}]" , paramsSign); return StringUtils.isNotBlank(paramsSign) && urlSign.equals(paramsSign); } }
最后
本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。
参考