作者:一剑天门

cnblogs.com/dslx/p/14116294.html

概述

与前端对接的API接口,如果被第三方抓包并进行恶意篡改参数,可能会导致数据泄露,甚至会被篡改数据,我主要围绕时间戳,token,签名三个部分来保证API接口的安全性

1.用户成功登陆站点后,服务器会返回一个token,用户的任何操作都必须带了这个参数,可以将这个参数直接放到header里。

2.客户端用需要发送的参数和token生成一个签名sign,作为参数一起发送给服务端,服务端在用同样的方法生成sign进行检查是否被篡改。

3.但这依然存在问题,可能会被进行恶意无限制访问,这时我们需要引入一个时间戳参数,如果超时即是无效的。

4.服务端需要对token,签名,时间戳进行验证,只有token有效,时间戳未超时,签名有效才能被放行。

开放接口

没有进行任何限制,简单粗暴的访问方式,这样的接口方式一般在开放的应用平台,查天气,查快递,只要你输入正确对应的参数调用,即可获取到自己需要的信息,我们可以任意修改参数值。

/** Description: 开放的接口* @author huangweicheng* @date 2020/12/21
*/
@RestController
@RequestMapping("/token")
public class TokenSignController {@Autowiredprivate TokenSignService tokenSignService;@RequestMapping(value = "openDemo",method = RequestMethod.GET)public List<PersonEntity> openDemo(int personId){return tokenSignService.getPersonList(personId);}
}

Token认证获取

用户登录成功后,会获取一个ticket值,接下去任何接口的访问都需要这个参数。我们把它放置在redis内,有效期为10分钟,在ticket即将超时,无感知续命。延长使用时间,如果用户在一段时间内没进行任何操作,就需要重新登录系统。扩展:记一次token安全认证的实践

@RequestMapping(value = "login",method = RequestMethod.POST)public JSONObject login(@NotNull String username, @NotNull String password){return tokenSignService.login(username,password);}

登录操作,查看是否有这个用户,用户名和密码匹配即可成功登录。

/** * * Description:验证登录,ticket成功后放置缓存中,* @param* @author huangweicheng* @date 2020/12/31   */ public JSONObject login(String username,String password){JSONObject result = new JSONObject();PersonEntity personEntity = personDao.findByLoginName(username);if (personEntity == null || (personEntity != null && !personEntity.getPassword().equals(password))){result.put("success",false);result.put("ticket","");result.put("code","999");result.put("message","用户名和密码不匹配");return result;}if (personEntity.getLoginName().equals(username) && personEntity.getPassword().equals(password)){String ticket = UUID.randomUUID().toString();ticket = ticket.replace("-","");redisTemplate.opsForValue().set(ticket,personEntity.getLoginName(),10L, TimeUnit.MINUTES);result.put("success",true);result.put("ticket",ticket);result.put("code",200);result.put("message","登录成功");return result;}result.put("success",false);result.put("ticket","");result.put("code","1000");result.put("message","未知异常,请重试");return result;}

Sign签名

把所有的参数拼接一起,在加入系统秘钥,进行MD5计算生成一个sign签名,防止参数被人恶意篡改,后台按同样的方法生成秘钥,进行签名对比。

/*** @param request* @return*/public static Boolean checkSign(HttpServletRequest request,String sign){Boolean flag= false;//检查sigin是否过期Enumeration<?> pNames =  request.getParameterNames();Map<String, String> params = new HashMap<String, String>();while (pNames.hasMoreElements()) {String pName = (String) pNames.nextElement();if("sign".equals(pName)) continue;String pValue = (String)request.getParameter(pName);params.put(pName, pValue);}System.out.println("现在的sign-->>" + sign);System.out.println("验证的sign-->>" + getSign(params,secretKeyOfWxh));if(sign.equals(getSign(params, secretKeyOfWxh))){flag = true;}return flag;}

重复访问

引入一个时间戳参数,保证接口仅在一分钟内有效,需要和客户端时间保持一致。

public static long getTimestamp(){long timestampLong = System.currentTimeMillis();long timestampsStr = timestampLong / 1000;return timestampsStr;}

需要跟当前服务器时间进行对比,如果超过一分钟,就拒绝本次请求,节省服务器查询数据的消耗

拦截器

每次请求都带有这三个参数,我们都需要进行验证,只有在三个参数都满足我们的要求,才允许数据返回或被操作。

public class LoginInterceptor implements HandlerInterceptor {@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws IOException {JSONObject jsonObject = new JSONObject();String ticket = request.getParameter("ticket");String sign = request.getParameter("sign");String ts = request.getParameter("ts");if (StringUtils.isEmpty(ticket) || StringUtils.isEmpty(sign) || StringUtils.isEmpty(ts)){jsonObject.put("success",false);jsonObject.put("message","args is isEmpty");jsonObject.put("code","1001");PrintWriter printWriter = response.getWriter();printWriter.write(jsonObject.toJSONString());return false;}//如果redis存在ticket就认为是合法的请求if (redisTemplate.hasKey(ticket)){System.out.println(redisTemplate.opsForValue().getOperations().getExpire(ticket));String values = (String) redisTemplate.opsForValue().get(ticket);//判断ticket是否即将过期,进行续命操作if (redisTemplate.opsForValue().getOperations().getExpire(ticket) != -2 && redisTemplate.opsForValue().getOperations().getExpire(ticket) < 20){redisTemplate.opsForValue().set(ticket,values,10L, TimeUnit.MINUTES);}System.out.println(SignUtils.getTimestamp());//判断是否重复访问,存在重放攻击的时间窗口期if (SignUtils.getTimestamp() - Long.valueOf(ts) > 600){jsonObject.put("success",false);jsonObject.put("message","Overtime to connect to server");jsonObject.put("code","1002");PrintWriter printWriter = response.getWriter();printWriter.write(jsonObject.toJSONString());return false;}//验证签名if (!SignUtils.checkSign(request,sign)){jsonObject.put("success",false);jsonObject.put("message","sign is invalid");jsonObject.put("code","1003");PrintWriter printWriter = response.getWriter();printWriter.write(jsonObject.toJSONString());return false;}return true;}else {jsonObject.put("success",false);jsonObject.put("message","ticket is invalid,Relogin.");jsonObject.put("code","1004");PrintWriter printWriter = response.getWriter();printWriter.write(jsonObject.toJSONString());}return false;}
}

访问

先登录系统,获取合法的ticket

生成一个合法的sign验证,获取测试ts,访问openDemo,即可正常访问。还可以将参数加密,将http换成https,就不一 一展开了。

demo代码

https://github.com/hwc4110/spring-demo1221

END

推荐好文

强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!
能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!

API接口的安全设计验证:ticket,签名,时间戳相关推荐

  1. api接口安全验证(sign签名和token验证)

    文章目录 背景 api接口安全类型 1.参数篡改 2.未授权用户访问 3.dos攻击 4.重要信息泄露 5.重放攻击 总结 背景 api的常用就不用多说了,在这个网络时代,小到天气信息,大到各种大数据 ...

  2. api接口文档中的签名是什么

    文章目录 前言 一.api文档中的签名是什么? 二.对文档规则中的签名算法的认识 三.生成签名的函数 总结 前言 初入程序员行列,随着工作的不断展开,我对业务上的逻辑也逐渐熟悉.在开发过程中少不了看a ...

  3. SpringCloud Gateway API接口安全设计(加密 、签名)

    点击关注公众号,实用技术文章及时了解 1 防止数据抓包窃取 1.1 风险简述 简述:当用户登录时,恶意攻击者可以用抓包工具可以拿到用户提交的表单信息,可以获取用户的账号密码,进而可以恶意访问网站. 1 ...

  4. 【345期】SpringCloud Gateway API 接口安全设计(加密 、签名)

    1 防止数据抓包窃取 1.1 风险简述 简述:当用户登录时,恶意攻击者可以用抓包工具可以拿到用户提交的表单信息,可以获取用户的账号密码,进而可以恶意访问网站. 1.2 RSA 非对称加密 1.2.1 ...

  5. api0.php,API接口 · HisiPHP V2开发手册 · 看云

    >[info] 快速导航 [TOC] ## 接口配置 在使用API之前你需要在后台做一个简单的API配置,如下图: ![](https://box.kancloud.cn/e41db0b7698 ...

  6. 对外API接口的安全性设计及鉴权方式

    对外API接口的安全性设计及鉴权方式 API鉴权方式 API Key + API Secret实现API鉴权 Cookie + Session实现API鉴权 token机制实现API鉴权 API接口的 ...

  7. php 设计api,PHP制作API接口

    需要单一入口文件,可以使用autoload来加载 //获取get参数 $m = !empty($_GET['m'])?$_GET['m']:'Index'; $a = !empty($_GET['a' ...

  8. 开发API接口的安全验证:token,参数签名,时间戳

    前言:服务端与前端对接的API接口,如果被第三方抓包并进行恶意篡改参数,可能会导致数据泄露和篡改数据,下面主要围绕token,签名,时间戳,三个部分来保证API接口的安全性. 强烈推荐,简单明了: 瞧 ...

  9. API接口签名生成算法和签名验证算法

    1.参考网上资料和书本资料,实现了API接口签名生成算法和签名验证算法. (1)参考资料:https://www.jianshu.com/p/d47da77b6419 (2)参考书籍:高级软件架构师教 ...

最新文章

  1. IOS网址解析-demo
  2. WCF+Nhibernate 序列化的问题。
  3. Kali Linux发布2020.1a版本
  4. 服务器安装系统时无法创建新的分区,重装系统出现“我们无法创建新的分区,也找不到现有的分区”...
  5. QT调用C++写的Dll
  6. Libra 新编程语言 :Move 所有权模型灵感竟是来自它……
  7. python正则表达式提取字符串密码_用python正则表达式提取字符串
  8. C++多继承构造和析构顺序
  9. PowerDesigner数据库设计PDM基于Excel的导入导出总结
  10. BDTC2016: 中航信 昆仑数据 兮易控股 宝信议题公布
  11. 备份蓝光光盘玩具总动员3,且Eclipse
  12. 怎么把ppt弄成链接的形式_如何在PPT中插入视频是嵌入而不是将视频文件设为链接...
  13. Swarm(bzz)节点服务器配置要求
  14. 固高运动卡的使用 4 运动之PT(点位)运动
  15. python倒背如流_python基本操作(五)
  16. 常见java空指针异常
  17. 五种方法安装Windows 7 64位系统
  18. C#长链接转短链接(调用新浪api)
  19. RDD简介,spark-shell,spark-submit提交任务简单示例
  20. 华科计算机博导刘云生论文,AAAI 2020线上分享 | 华科Oral论文:点云中3D目标检测的鲁棒性...

热门文章

  1. 全球最快!小米发布超级无线闪充技术,小米9 Pro 5G将首发搭载
  2. 拿下阿里投资 回血的网易云音乐能成功突围吗?
  3. 网友投诉顺丰快递员私拆快递物品摆拍、言语骚扰 官方处理来了...
  4. 又栽了?苹果侵犯高通三项专利需赔偿3100万美元
  5. jmeter之JDBC类组件
  6. 前端面试汇总(Bootstrap框架)
  7. 告诉家里做饭的人,这些食物一起吃才是大补!
  8. glassfish显示不了html文件,Glassfish websocket无法正常工作(示例代码)
  9. Android 源码分析 Activity的启动模式
  10. ubuntu apache服务器和gitweb服务器搭建