小Hub领读:
如果保证接口的安全,有想法?坦白说呀,第一种方法我在自己的公众号私人项目中经常用,哈哈哈
作者:低调的码农
https://juejin.im/post/6844903877985173511
场景
我们做的产品是 To B 的,那么我们自身会有一个云运营平台的系统,这个系统包含我们所有项目的运营管理数据,在一个月前,我们还不需要想对外提供服务,但是有一天我们数据被其他团队所需要了,需求就来了?
需求:我们要做一个接口认证,用来识别对方服务是啥?
小 A 同学领到任务开始是很开心的,立马做了好几个方案给领导审阅。
方案大爆炸
一、直接在 header 头部或者 url 地址给一个私有 token
约定client的token值为12345678,
那么请求的url地址为:
/remote/getApk?token=12345678
服务端接收到token后,进行匹配判断是否合法token,不合法就退出,合法就是后续操作。
简单,非常简单,调用方直接拿到这个 token 写入 header 头部或者 url,在服务端拿到后进行简单匹配逻辑来确定调用方是否正确,就完事了,从明面上来讲,这个已经满足需求了,但是新的问题来了?
如果我这个 token 被第三方截取怎么办?
答:上 https,安全
没毛病的,https 是安全,因为在 http 协议的基础上增加一层 SSL/TLS(可以理解为 http 是裸奔,SSL/TLS 是盔甲,遮盖住重要的信息),但是在我们这小门小户要实现全部 https 不太可能,而且 https 对于客户端的调用也不是那么方便,那么接下来又怎么办呢?
二、加上 ip 白名单
其实这里根本不需要加参数,服务端默认就可以获取客户端的 ip,这就保证一点,如果我们 token 被劫持,就算给你发,也没啥用,没错,在很多内部系统中,我们设计接口校验就算基于它来做的,因为这个更简单,基本两边接口完全不需要改东西,写完就可以调,就一个 ip 白名单配置。搜索公纵号:MarkerHub,关注回复[ vue ]获取前后端入门教程!
那有没有可能这个包被别人劫持,然后进行 ip 代理,然后来请求呢?
三、token 作为加密盐值,cs 作为双方加密认证
前提:
需要 ip 白名单
需要为这个调用方产出一个 token(salt)
这里约定就不是token了,使用一个双方约定的密码盐值salt=123456
GET /remote/getApk?md5=043c00e6c7ff021e8cc4d394d3264cb5&sign=md5(043c00e6c7ff021e8cc4d394d3264cb5+123456)
sign 计算方式:将我们请求的参数按key的正序排序,把里面的值进行字符串连接并且加上salt,再进行一个md5计算,当然可以选择其他hash算法,例如sha1等
这种方案在服务端,我们一样实现这一算法,并且最终校验这个 sign 值是否一样,当然这个方案并不能解决我们刚刚一开始说不安全的问题,因为网络截取是个很平常的事情。
那么有没有办法截取了用不了呢?
答案是肯定的,那我们在 url 地址添加一个请求的时间戳
GET /remote/getApk?t=1561969549&md5=043c00e6c7ff021e8cc4d394d3264cb5&sign=md5(043c00e6c7ff021e8cc4d394d3264cb5+1561969549+123456)
sign 计算方式:将我们请求的参数按key的正序排序,把里面的值进行字符串连接并且加上salt,再进行一个md5计算,当然可以选择其他hash算法,例如sha1等
这里是加一个时间戳作为 sign 的参数,那么可以理解为这个 sign 值是在特定时间内有效,在服务端接收到请求后,可以优先判断时间戳与服务端时间偏移,如果在一分钟之内,那么这个都是可以请求,超过说明这个已经过期了
如果我们对于接口请求严格限制,那么我们每次请求过的 sign 值不能重复,这个涉及到另外话题:
可以简单说一下:我们可以将每个时间戳建立一个桶,每个桶里面装的就是这些 sign 值,这些时间戳的过期时间与服务端判断的过期时间一致(如果 t 字段过期,那么就走不到这一步),就是这么简单哈。
看到这里有同学肯定会问:时间戳不一样咋办,客户端与服务端时间戳肯定会不一样的?
能想到这的同学,真的非常聪明,因为是真的有这个问题出现,当然不是这个场景,只要是时间区间判断的问题,都要考虑双方时间戳的问题
公司统一使用时间服务器,调用双方同步这个服务器时间。
客户端不定时同步服务端的时间
总结
其实这个方案设计是仅限于我们企业内部服务相互调用的一个接口设计,刚开始接到任务都会想 jwt oauth2.0 等方案,后来仔细想想,我们压根不需要那么复杂的逻辑来做,因为我们面向的是服务,不是面向独立个体的用户,当然用 jwt 和 oauth2.0 也可以,就是我们接口的请求调用就变成登录、校验、鉴权 等方式了。
谢谢各位同学查阅
(完)
MarkerHub文章索引:(点击阅读原文直达)
https://github.com/MarkerHub/JavaIndex
【推荐阅读】
为什么MySQL不推荐使用uuid或者雪花id作为主键?
Docker 实战总结(非常全面)这是我读过写得最好的【秒杀系统架构】分析与实战!
你的登录接口真的安全吗?
权限管理系统之集成Shiro实现登录、url和页面按钮的访问控制
Vue项目使用拦截器和JWT验证 完整案例
1万七千字精讲,JDK8 的 Lambda、Stream、LocalDate 骚技能
为什么建议大家使用 Linux 开发?爽(外加七个感叹号)
为什么阿里巴巴要禁用Executors创建线程池?
好文章!点个在看!