API接口的安全设计验证:ticket,签名,时间戳
作者:一剑天门
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,签名,时间戳相关推荐
- api接口安全验证(sign签名和token验证)
文章目录 背景 api接口安全类型 1.参数篡改 2.未授权用户访问 3.dos攻击 4.重要信息泄露 5.重放攻击 总结 背景 api的常用就不用多说了,在这个网络时代,小到天气信息,大到各种大数据 ...
- api接口文档中的签名是什么
文章目录 前言 一.api文档中的签名是什么? 二.对文档规则中的签名算法的认识 三.生成签名的函数 总结 前言 初入程序员行列,随着工作的不断展开,我对业务上的逻辑也逐渐熟悉.在开发过程中少不了看a ...
- SpringCloud Gateway API接口安全设计(加密 、签名)
点击关注公众号,实用技术文章及时了解 1 防止数据抓包窃取 1.1 风险简述 简述:当用户登录时,恶意攻击者可以用抓包工具可以拿到用户提交的表单信息,可以获取用户的账号密码,进而可以恶意访问网站. 1 ...
- 【345期】SpringCloud Gateway API 接口安全设计(加密 、签名)
1 防止数据抓包窃取 1.1 风险简述 简述:当用户登录时,恶意攻击者可以用抓包工具可以拿到用户提交的表单信息,可以获取用户的账号密码,进而可以恶意访问网站. 1.2 RSA 非对称加密 1.2.1 ...
- api0.php,API接口 · HisiPHP V2开发手册 · 看云
>[info] 快速导航 [TOC] ## 接口配置 在使用API之前你需要在后台做一个简单的API配置,如下图: ![](https://box.kancloud.cn/e41db0b7698 ...
- 对外API接口的安全性设计及鉴权方式
对外API接口的安全性设计及鉴权方式 API鉴权方式 API Key + API Secret实现API鉴权 Cookie + Session实现API鉴权 token机制实现API鉴权 API接口的 ...
- php 设计api,PHP制作API接口
需要单一入口文件,可以使用autoload来加载 //获取get参数 $m = !empty($_GET['m'])?$_GET['m']:'Index'; $a = !empty($_GET['a' ...
- 开发API接口的安全验证:token,参数签名,时间戳
前言:服务端与前端对接的API接口,如果被第三方抓包并进行恶意篡改参数,可能会导致数据泄露和篡改数据,下面主要围绕token,签名,时间戳,三个部分来保证API接口的安全性. 强烈推荐,简单明了: 瞧 ...
- API接口签名生成算法和签名验证算法
1.参考网上资料和书本资料,实现了API接口签名生成算法和签名验证算法. (1)参考资料:https://www.jianshu.com/p/d47da77b6419 (2)参考书籍:高级软件架构师教 ...
最新文章
- IOS网址解析-demo
- WCF+Nhibernate 序列化的问题。
- Kali Linux发布2020.1a版本
- 服务器安装系统时无法创建新的分区,重装系统出现“我们无法创建新的分区,也找不到现有的分区”...
- QT调用C++写的Dll
- Libra 新编程语言 :Move 所有权模型灵感竟是来自它……
- python正则表达式提取字符串密码_用python正则表达式提取字符串
- C++多继承构造和析构顺序
- PowerDesigner数据库设计PDM基于Excel的导入导出总结
- BDTC2016: 中航信 昆仑数据 兮易控股 宝信议题公布
- 备份蓝光光盘玩具总动员3,且Eclipse
- 怎么把ppt弄成链接的形式_如何在PPT中插入视频是嵌入而不是将视频文件设为链接...
- Swarm(bzz)节点服务器配置要求
- 固高运动卡的使用 4 运动之PT(点位)运动
- python倒背如流_python基本操作(五)
- 常见java空指针异常
- 五种方法安装Windows 7 64位系统
- C#长链接转短链接(调用新浪api)
- RDD简介,spark-shell,spark-submit提交任务简单示例
- 华科计算机博导刘云生论文,AAAI 2020线上分享 | 华科Oral论文:点云中3D目标检测的鲁棒性...
热门文章
- 全球最快!小米发布超级无线闪充技术,小米9 Pro 5G将首发搭载
- 拿下阿里投资 回血的网易云音乐能成功突围吗?
- 网友投诉顺丰快递员私拆快递物品摆拍、言语骚扰 官方处理来了...
- 又栽了?苹果侵犯高通三项专利需赔偿3100万美元
- jmeter之JDBC类组件
- 前端面试汇总(Bootstrap框架)
- 告诉家里做饭的人,这些食物一起吃才是大补!
- glassfish显示不了html文件,Glassfish websocket无法正常工作(示例代码)
- Android 源码分析 Activity的启动模式
- ubuntu apache服务器和gitweb服务器搭建