1、编写接口过滤器


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.*;/*** @author : nyl* create at:  2022/11/7  10:36 下午* @description:*/
@Slf4j
@Order(1)
@WebFilter
@Component
public class ApiReqFilter implements Filter {/*** 签名验证时间(TIMES =分钟 * 秒 * 毫秒)* 当前设置为:5分钟有效期*/protected static final Integer TIMES = 5 * 60 * 1000;//需要验签的请求地址public List<String> ignoreUrl= Arrays.asList("/wash/wsorder/getOrderList","/qm-currency/refundlog/getRefundList","/wash/amountwater/getAmountWaterList");@Overridepublic void init(FilterConfig filterConfig) {System.out.println("ApiReqFilter---->init()");}@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;Map<String, Object> map = new HashMap<>();//获取请求URIString requestURI = request.getRequestURI();System.out.println(requestURI+"---");if (!ignoreUrl.contains(requestURI)) {// 放行chain.doFilter(request, response);} else {// 判断请求方式String method = request.getMethod();if ("POST".equals(method)) {// 获取请求Body参数,需要使用 BodyReaderHttpServletRequestWrapper进行处理// 否则会出现异常:I/O error while reading input message; nested exception is java.io.IOException: Stream closed// 原因就是在拦截器已经读取了请求体中的内容,这时候Request请求的流中已经没有了数据// 解决流只能读取一次的问题:先读取流,然后在将流重新写进去就行了ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);String body = HttpHelper.getBodyString(requestWrapper);String bodyString = URLDecoder.decode(body, "utf-8");if (StrUtil.isEmpty(bodyString)) {response.setCharacterEncoding("utf-8");PrintWriter writer = response.getWriter();response.setHeader("Content-type", "application/json;charset=UTF-8");response.setCharacterEncoding("utf-8");map.put("code", 400);map.put("msg", "请求参数不能为空");writer.print(JSONObject.toJSONString(map));writer.close();return;}// 解析参数转JSON格式// bodyString = "{" + bodyString.replace("&", "',").replace("=", ":'") + "'}";JSONObject jsonObject = JSONObject.parseObject(bodyString);// 验签boolean validation = validation(jsonObject, response);if (!validation) {return;}// 放行chain.doFilter(request, response);}if ("GET".equals(method)) {// 获取请求参数Map<String, String> allRequestParam = getAllRequestParam(request);Set<Map.Entry<String, String>> entries = allRequestParam.entrySet();// 参数转JSON格式JSONObject jsonObject = new JSONObject();entries.forEach(key -> {jsonObject.put(key.getKey(), key.getValue());});// 验签boolean validation = validation(jsonObject, response);if (!validation) {return;}// 放行chain.doFilter(request, response);}}}/*** 验签** @param body     请求参数* @param response* @return* @throws IOException*/private boolean validation(JSONObject body, HttpServletResponse response) throws IOException {// 拿出请求签名String sign = body.getString("sign");Assert.notBlank(sign, "sign is required");Assert.notNull(body.getLong("dateTime"), "dataTime is required");body.remove("sign");// 根据APPID查询的密钥进行重签String sign1 = getSign(body);Map<String, Object> map = new HashMap<>();response.setCharacterEncoding("utf-8");PrintWriter writer = response.getWriter();response.setHeader("Content-type", "application/json;charset=UTF-8");response.setCharacterEncoding("utf-8");// 校验签名if (!sign.equals(sign1)) {map.put("code", 10000);map.put("msg", "签名错误");writer.print(JSONObject.toJSONString(map));return false;}// 校验签名是否失效long thisTime = System.currentTimeMillis() - body.getLong("dateTime");if (thisTime > TIMES) {// 比对时间是否失效map.put("code", 20000);map.put("msg", "签名失效");writer.print(JSONObject.toJSONString(map));return false;}return true;}/*** 计算签名** @param params* @return*/public static String getSign(JSONObject params) {// 从缓存中获取密钥String key = "自己定义key";// 参数进行字典排序String sortStr = getFormatParams(params);// 将密钥key拼接在字典排序后的参数字符串中,得到待签名字符串。sortStr += "key=" + key;// 使用md5算法加密待加密字符串并转为大写即为sign// String sign = SecureUtil.md5(sortStr).toUpperCase();String sign = DigestUtils.md5DigestAsHex(sortStr.getBytes()).toUpperCase();return sign;}/*** 参数字典排序** @param params* @return*/public static String getFormatParams(Map<String, Object> params) {List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(params.entrySet());Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {public int compare(Map.Entry<String, Object> arg0, Map.Entry<String, Object> arg1) {return (arg0.getKey()).compareTo(arg1.getKey());}});String ret = "";for (Map.Entry<String, Object> entry : infoIds) {ret += entry.getKey();ret += "=";ret += entry.getValue();ret += "&";}return ret;}/*** 获取客户端GET请求中所有的请求参数** @param request* @return*/private Map<String, String> getAllRequestParam(final HttpServletRequest request) {Map<String, String> res = new HashMap<String, String>();Enumeration<?> temp = request.getParameterNames();if (null != temp) {while (temp.hasMoreElements()) {String en = (String) temp.nextElement();String value = request.getParameter(en);res.put(en, value);//如果字段的值为空,判断若值为空,则删除这个字段>if (null == res.get(en) || "".equals(res.get(en))) {res.remove(en);}}}return res;}
}

2、工具类


import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration;/*** @author : nyl* create at:  2022/11/7  10:39 下午* @description:*/
public class BodyReaderHttpServletRequestWrapper extendsHttpServletRequestWrapper {private final byte[] body;public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);Enumeration e = request.getHeaderNames()   ;while(e.hasMoreElements()){String name = (String) e.nextElement();String value = request.getHeader(name);System.out.println(name+" = "+value);}body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener listener) {}@Overridepublic int read() throws IOException {return bais.read();}};}@Overridepublic String getHeader(String name) {return super.getHeader(name);}@Overridepublic Enumeration<String> getHeaderNames() {return super.getHeaderNames();}@Overridepublic Enumeration<String> getHeaders(String name) {return super.getHeaders(name);}}

import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;/*** @author : nyl* create at:  2022/11/7  10:40 下午* @description:*/
public class HttpHelper {public static String getBodyString(ServletRequest request) {StringBuilder sb = new StringBuilder();InputStream inputStream = null;BufferedReader reader = null;try {inputStream = request.getInputStream();reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));String line = "";while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {e.printStackTrace();} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println("sb = " + sb);return sb.toString();}
}

3、编写测试类

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import org.springblade.common.apiSign.ApiReqFilter;
import org.springframework.boot.test.context.SpringBootTest;
import org.testng.annotations.Test;import java.util.*;/*** @author : nyl* create at:  2022/11/7  10:41 下午* @description:*/
@SpringBootTest
public class TestHttpReq {public static String secretKey = "自己定义的key";@Testpublic void testPost() {JSONObject data = new JSONObject();data.put("name", "xxx");data.put("age", "11");data.put("app_id", "1234");long dateTime = new Date().getTime();data.put("date_time", "1656926899731");String sign = ApiReqFilter.getSign(data);//修改密钥为数据加密后加密串data.put("sign", sign);HttpResponse response = HttpRequest.post("localhost:8088/wash/wsorder/list").form(data).contentType("application/json").execute();Object jsonObject = JSONObject.parse(response.body().trim());System.out.println("jsonObject = " + jsonObject);}@Testpublic void testGet() {String url = "localhost:8088/wash/amountwater/getAmountWaterList";long dateTime = new Date().getTime();//传入参数JSONObject data = new JSONObject();data.put("dateTime", dateTime);data.put("current", 1);data.put("size", 1);data.put("tenantId", "183571");data.put("startTime", "2020-02-09");data.put("endTime", "2023-02-09");String sign = ApiReqFilter.getSign(data);System.out.println(sign+"----"+data);url = url + "?startTime=2020-02-09&endTime=2023-02-09&current=1&size=1&tenantId=183571&dateTime=" + dateTime + "&sign=" + sign;HttpResponse response = HttpRequest.get(url).execute();System.out.println(url);System.out.println("response.body() = " + response.body().trim());}}

4、编写调用接口 (接口自己实现即可)

 @GetMapping("/getOrderList")@ApiOperation(value = "分页查询订单列表", notes = "传入wsOrder")public void listInfo(QOrderDTO qOrderDTO, Query query, HttpServletResponse httpServletResponse) throws IOException {JSONObject json = new JSONObject();try {IPage<WsOrderVO> data = wsOrderService.listPageVo(Condition.getPage(query), BeanUtil.copyProperties(qOrderDTO,QueryGoodsOrderDTO.class));json.put("code", 200);json.put("msg", "success");json.put("data", data);} catch (Exception e) {e.printStackTrace();json.put("code", 500);json.put("msg", "调用失败,请稍后重试!");json.put("data", null);}httpServletResponse.setCharacterEncoding("utf-8");httpServletResponse.setContentType("application/json; charset=utf-8");PrintWriter writer = httpServletResponse.getWriter();writer.write(json.toString());writer.flush();writer.close();}

java实现md5签名实现对外调用接口相关推荐

  1. java对外接口安全问题_怎么保证对外暴露接口的安全性(调用频率限制)

    如何限制接口调用者对接口的调用频率? 问题:对某个对外暴露的接口加一个限制:调用者一分钟之内调用次数不能超过100次,如果超过100次就直接返回给调用者失败的信息. 给调用者一个SECRET,每次调用 ...

  2. java对外sdk提供接口_Android SDK封装,对外提供接口

    项目中需要把连接服务器的部分做成一个service并生成一个jar模块.其他产品就可通过这个包来快速的开发连接服务器的应用软件.做成一个service的优点是: 1. 在后台运行,可以一直保持与服务器 ...

  3. java异步调用微信接口_微信支付V3 SDK(Java版,支持同步异步调用)

    我们在开发微信支付时,发现微信官方已经对SDK做了升级,V3版本的SDK从设计上符合RESTful规范. 我们再在开源库中寻找是否有现成de开箱即用.并且支持响应式编程的SDK版本.经过一凡寻找,令我 ...

  4. 【Android NDK 开发】JNI 方法解析 ( C/C++ 调用 Java 方法 | 函数签名 | 调用对象方法 | 调用静态方法 )

    文章目录 I . 调用 Java 方法流程 II . 获取 jclass 对象 ( GetObjectClass ) III . 获取 jclass 对象 ( FindClass ) IV . JNI ...

  5. retryexec.java 94_解决feign调用接口不稳定的问题

    我就废话不多说了,大家还是直接看代码吧~ Caused by: java.net.SocketException: Software caused connection abort: recv fai ...

  6. ictclas包 java_ICTCLAS分词系统Java调用接口在Eclipse中的安装

    ICTCLAS分词系统Java调用接口在Eclipse中的安装 实验环境:JDK1.5.Eclipse3.1.XP操作系统 分词系统Java接口解压包:d:\fenci(http://www.nlp. ...

  7. java md5 签名_java md5签名

    签名算法 将所有请求参数(key,value 为一组),对数据结构按照 key 的升序,重新排序, 需要对 null 值进行过滤,需要将 boolean 型进行转换为 1 和 0 将排序后参数组合为新 ...

  8. java如何调用接口股票的?

    java如何调用接口股票的?在学习java的时候,我们知道的过程java它相当于一个简单的浏览器,通过向相应的服务发送数据信息并返回服务器的响应结果.Java里面主要是封装的httpclient来做手 ...

  9. java调用接口实现的方法_java调用接口的实现方法

    java调用接口的实现方法 发布时间:2020-06-29 11:08:46 来源:亿速云 阅读:78 作者:Leah 本篇文章给大家分享的是有关java调用接口的实现方法,小编觉得挺实用的,因此分享 ...

最新文章

  1. 计算机网络知到马惜平答案,计算机网络实习用Dreamweaver搭建个人网站
  2. LVS的DR模型的实现
  3. bootstrap-table页码ALL显示为NAN
  4. 框架和库有什么区别? [关闭]
  5. 2003服务器被入侵,如果还原Gest用户,删除隐藏用户
  6. Bellman-Ford算法和SPFA算法
  7. 区块链技术怎么构架落地应用?
  8. php写简单接口_php写接口,对比两种写法
  9. 【配置属性】—Entity Framework 对应表字段的类型的设定配置方法
  10. 墙后的所有姿势,全被“瞎眼”AI透视
  11. DS8700 的CPU、缓存的选择及配置
  12. Django的数据迁移
  13. 身份证号正则验证及提取性别出生年月出生时间
  14. numpy一行转为一列
  15. 深入理解Java类加载器(2):线程上下文类加载器
  16. 基于FPGA的DDS混频及原理
  17. 推荐一个基于 SpringCloud 设计精良的网上商城
  18. 单反相机坏点和噪点测试软件,坏点和噪点测试程序(照片检测工具)
  19. 写正则好用的测试工具
  20. 智能设备主要有哪些特点

热门文章

  1. 高性能webdav服务器,webdav服务器
  2. IntelliJ IDEA:安装/搭建/配置/插件
  3. 关于使用[MASK]做完形填空时需要注意的点
  4. 火焰检测 python
  5. 微信公众号还会有二次繁荣吗?
  6. 2020年9月电子学会Python等级考试试卷(三级)考题解析
  7. ev3编程 越野机器人_Lego ev3机器人怎么编程
  8. Mars3D(含Cesium)数据及服务篇:单体小模型转为glTF格式
  9. java实现大乐透彩票
  10. linux中zip文件解压命令,Linux中zip压缩和unzip解压缩命令使用方法