文章目录
-
- 一.前言
- 二.安全措施
-
- 1.数据加密
- 2.数据加签
- 3.时间戳机制
- 4.AppId机制
- 5.限流机制
- 6.黑名单机制
- 7.数据合法性校验
- 三.如何实现
-
- 1.数据加密
- 2.数据加签
- 3.时间戳机制
- 4.AppId机制
- 5.限流机制
- 6.黑名单机制
- 7.数据合法性校验
- 四.源码
一.前言
结合我之前写的【Java基础】加密与安全基础 可以看本文章时更加熟悉 “加密以及安全”的基础概念
个人觉得安全措施大体来看主要在2个方面
- 是如何保证
数据在传输过程中不被窃取
- 是数据已经到达服务器端,
服务器端验证传过来的数据没有被篡改,如何不被攻击
二.安全措施
1.数据加密
我们知道数据在传输过程中是很容易被
抓包
的,如果直接传输比如通过
http协议
,那么用户传输的数据可以被任何人获取,所以必须对数据加密。常见的做法对关键字段加密,比如:用户密码直接通过md5加密。加密的作用是保证数据在传输过程中不被窃取。
- 现在主流的做法是使用
,在http和tcp之间添加一层加密层https协议
,这一层负责数据的加密和解密;(SSL层)
2.数据加签
数据加签就是由发送者生成一段无法伪造的一段字符串,来保证数据在传输过程中没有被被抓包篡改。
你可能会问数据如果已经通过
https
加密了,还有必要进行加签吗?
- 数据在传输过程中经过加密,理论上就算被抓包,也无法对数据进行篡改;但是我们要知道加密的部分其实只是在
,现在很多服务在外网
中都需要经过很多服务跳转,所以这里的加签可以内网
。防止内网中数据被篡改
3.时间戳机制
数据是很容易被抓包的,但是经过如上的
加密
,
加签
处理,就算拿到数据也不能看到真实的数据。但是有不法者
不关心真实的数据,而是直接拿到抓取的数据包进行恶意请求
。这时候可以使用时间戳机制
- 在每次请求中加入当前的时间,服务器端会拿到
,比如5分钟内。这样恶意请求的数据包是无法更改里面时间的,所以5分钟后就视为非法请求了。当前时间和请求中的时间相减,看看是否在一个固定的时间范围内
4.AppId机制
大部分网站基本都需要用户名和密码才能登录,并不是谁来能使用我的网站,这其实也是一种安全机制。对应的对外提供的接口其实也需要这么一种机制,并不是谁都可以调用,
需要使用接口的用户需要在后台开通appid
,提供给用户相关的
密钥
(appSecret)。在调用的接口中需要提供appid以及密钥(主要用于与生成签名sign),服务器端会进行相关的验证;
5.限流机制
本来就是真实的用户,并且开通了appid,但是出现
频繁调用接口
的情况;这种情况需要给相关appid限流处理
- 常用的限流算法有
和令牌桶
。漏桶算法
6.黑名单机制
如果此appid进行过很多非法操作,或者说专门有一个
中黑系统
,经过分析之后直接将此appid列入
黑名单
,
所有请求直接返回错误码
.
7.数据合法性校验
这个可以说是每个系统都会有的处理机制,
只有在数据是合法的情况下才会进行数据处理
。每个系统都有自己的验证规则,当然也可能有一些常规性的规则,比如身份证长度和组成,电话号码长度和组成等等;
三.如何实现
以上大体介绍了一下常用的一些接口安全措施,当然可能还有其他我不知道的方式,希望大家补充,下面看看以上这些方法措施,具体如何实现;
1.数据加密
现在主流的加密方式有
对称加密(单钥加密)
和
非对称加密(双钥加密)
。
- 对称加密:对称密钥的
和加密
中使用的解密
密钥是相同的
- 常见的对称加密算法有:
,DES
AES
- DES:
,一共有三个参数入口(原文,密钥,加密模式)。而3DES只是DES的一种模式,是以DES为基础更安全的变形,对数据进行了三次加密,也是被指定为比较老的算法
AES的过渡算法
。
-
AES:高级加密标准,新一代标准,加密速度更快,安全性更高(优先选择)
- 优点:
,适合对大数据进行加解密。计算速度快
- 缺点:是在数据传送前,
,然后使双方都能保存好秘钥,发送方和接收方必须商定好密钥
。如果一方的秘钥被泄露,那么加密信息也就不安全了
密钥只有一把,所以密钥的保存变得很重要。一旦密钥泄漏,密码也就被破解。
- 常见的对称加密算法有:
由于对称加密加解密速度快,因此可以和非对称加密混合使用,可以使用非对称加密方式加密对称加密的密钥,来保护密钥的安全。
- 非对称加密:
,由加密和解密使用不同的密钥
会生成服务端
,一对密钥
存放在私钥
,服务端
可以发布给公钥
使用。任何人
用公钥加密的数据,只能用和它对应的私钥解密,用私钥加密也只能同与之对应的公钥解密。
- 常见的非对称加密是
算法RSA 加密
- 优点: 比起对称加密更加安全
- 缺点: 加解密的速度比对称加密
太多了(如:密钥对的生成,根据公钥反推私钥) 不适合对大数据进行加解密慢
- 场景: 最常用的使用场景就是
和数字签名
,用作密码传输
时使用私钥加密,公钥解密;用作数字签名
时,使用公钥加密,私钥解密。加密解密
同时生成公钥和私钥应该相对比较容易,但是从公钥推算出私钥,应该是很困难或者是不可能的
- 常见的非对称加密是
- 两种方式各有优缺点,而
的实现方式正好是https
,结合了两种加密方式
,在安全和性能方面都比较好整合了双方的优点
对称加密和非对称加密代码实现,Java提供了相关的工具类可以直接使用,此处不过多介绍,关于https如何配置使用相对来说复杂一些 HTTPS分析与实战
2.数据加签
3种数据签名安全策略:
消息摘要
,
数字签名
,
数字签名+加密[证书]
安全策略 | 描述 | 安全级别 |
---|---|---|
消息摘要(Digest),也称消息Hash | 将数据和Key(自定义密钥)组合后进行hash | ,密钥安全性非常低。在密钥安全情况下能基本保障数据的不可篡改性。 |
数字签名(Signature) | 使用证书和非对称签名算法对数据进行签名 | ,能够保障数据的不可篡改性和不可抵赖性,但是不能保障数据的私密性 |
签名-加密[证书] | 使用证书和非对称算法对数据签名,使用一次一密的密钥和对称算法对数据进行加密 | ,能够保障数据的不可篡改性和不可抵赖性,而且能保障数据的私密性。 |
- 机密性(Confidentiality): 未经许可不许看
- 完整性(Integrity) : 不许篡改
- 可用性(Availability) : 防止不可用
- 不可抵赖性(Non-Repudiation): 用户不能否认其行为
1.消息摘要(Digest)
- 消息摘要使用比较多的摘要算法(也称Hash算法)是有
,将需要提交的数据通过某种方式组合成一个字符串,然后通过hash算法生成一段加密字符串,这段字符串就是数据包的MD5、SHA-1、SHA-256
。,比如:签名signature
这个固定长度的 Hash 值,就是这份数据的摘要,也称为指纹。
str = 参数1={参数1}&参数2={参数2}&……&参数n={参数n}&signature={用户密钥};
MD5.encrypt(str);
注意:最后的
用户密钥signature
,
客户端和服务端都有一份
,这样会更加安全;
- 消息摘要原理:
,并且计算结果具有Hash算法不可逆
,在唯一性
的隐私得到保证的情况下,可以保证完整性用户密钥
- 消息摘要缺陷:
的是用户密钥
的,隐私性很难保证。明文传输
2.数字签名(Signature)
如果用「公钥」对数据加密,用「私钥」去解密,这是
「加密」
; 反之用「
私钥」对数据加密
,用
「公钥」去解密
,这是
「签名」
!!!
简单地看,似乎没有区别,只是换了个名字。但实际上,两者的用途完全不一样。 因为,因为所有人都可以用公钥去解密。 但「签名」却能用于保证
所有人都持有公钥,所以「签名」并不能保证数据的安全性
。因为
数据的准确性和不可否认性
,所以
公钥和私钥是一一对应的
当一个公钥能解密某个密文时,说明这个密文一定来自于私钥持有者。
高效的数字签名方案: 将
摘要算法(Hash算法)
和
非对称加密结合
使用。
-
:客户端先用如何签名
计算Hash算法
的明文数据
,再对这个Hash值
。这样就能较快速地得到了Hash值用 “私钥“ 加密
,将明文数据以及密文同时传给服务端原始信息的签名
-
:服务端先用如何验证
计算相同的Hash算法
,再用客户端传递明文数据的Hash值
,得到收到的Hash值,最后对比这两个Hash值判断是否相等。如果不相等说明数据不可信。“公钥“ 对 客户端传递的签名进行解密
如果明文数据特别庞大,直接使用非对称加密生成签名会导致加解密的效率特别底下(慢慢慢),这也是为什么上面会 先将明文数据hash后在通过私钥加密
具体操作
- 客户端 对
做一个明文数据
计算,对md5/SHA
,客户端 将计算后的值通过 "私钥" 加密得到密文(签名)
和明文数据
发送给服务端密文
- 服务端 对
通过密文
得到“公钥解密”
,同时 服务端 对值A
做一个明文
计算得到md5/SHA
值B
- 服务端比较客户端与服务Hash的明文值A与值B,
,如果不相等说明数据不可信。相同得验证通过
能够保障
不可篡性
和
不可抵赖性
,但是
不能保障数据的私密性
(明文传输)
- 即使他人截获并篡改了
,由于「明文数据」
是保密的,篡改者也无法生成正确的「私钥」
。所以能保证「签名」
。数据的完整
3.签名+加密[证书]过程
- 客户端生成一个
,作为随机字符串
,然后把这个password通过password
,把B公钥加密生成密文C
,A明文通过password加密生成密文B
- 同时把
做A明文
计算后的值通过MD5/SHA
加密得到A私钥
, 把签名D
和密文B
和密文C
发给服务端,签名D
,然后通过服务端通过私钥解密文C得到password
就可以得到password解密文B
,同时A明文
可以用来签名
,以及验证发送者是不是A
。A发送的数据有没有被第三方修改过
假设存在一个恶意的一方X,冒充了A,发送了
密文B(password生成)
,
密文C
,服务端收到数据后,仍然可以正常解密得到明文,但是却
无法证明这个明文数据是A发送的还是恶意用户B发送的
。
签名D
的含义就是
A自己签名
,服务端可以验证。
X
由于没有
A的私钥
,这个签名它无法冒充,会被服务端识别出来。
3.时间戳机制
解密后
的数据,经过
签名认证
后,我们拿到数据包中的
客户端时间戳字段
,然后
用服务器当前时间去减客户端时间,看本次请求是否超时
。
伪代码如下:
long interval=5*60*1000;//超时时间
long clientTime=request.getparameter("clientTime");
long serverTime=System.currentTimeMillis();
if(serverTime-clientTime>interval){
return new Response("超过处理时长")
}
4.AppId机制
生成一个唯一的appId以及对应的appSecret(密钥)。密钥使用字母、数字等特殊字符随机生成即可;
- 生成唯一appId根据实际情况看
,但是不管是否全局唯一最好让生成的Id有如下属性:是否需要全局唯一
- 趋势递增:这样在保存数据库的时候,使用索引性能更好。
- 信息安全:尽量不要连续的,容易发现规律。
- 关于
生成的方式常见的有类全局唯一Id
(Snowflake 俗称雪花算法,用于生成Snowflake
)方式等;分布式自增 ID
5.限流机制
常用的限流算法包括:
固定窗口计数器算法
、
滑动窗口计数器算法
、
漏桶限流
,
令牌桶限流
,
计数器限流:”计数器是一种比较简单粗暴的算法,主要用来限制总并发数,比如数据库连接池、线程池、秒杀的并发数;计数器限流只要一定时间内的总请求数超过设定的阀值则进行限流;
-
固定窗口计数器算法
规定我们单位时间处理的请求数量。比如我们规定我们的一个接口一分钟只能访问 10 次的话。使用固定窗口计数器算法的话可以这样实现:
- 给定一个变量 counter 来记录处理的请求数量,当 1 分钟之内处理一个请求之后 counter+1,1 分钟之内的如果 counter=100 的话,后续的请求就会被全部拒绝。等到 1 分钟结束后,将 counter 回归成 0,重新开始计数(ps:只要过了一个周期就讲 counter 回归成 0)。
- 这种限流算法无法保证限流速率,因而无法保证突然激增的流量。比如我们限制一个接口一分钟只能访问 10 次的话,前半分钟一个请求没有接收,后半分钟接收了 10 个请求。
-
滑动窗口计数器算法
算的上是固定窗口计数器算法的升级版。滑动窗口计数器算法相比于固定窗口计数器算法的优化在于:
- 它把时间以一定比例分片,比如一分钟分为 6 个区间,每个区间为 10s。每过一定区间的时间,就抛弃最前面的一个区间,如下图所示。如果当前窗口的请求数量超过了限制数量的话,就拒绝后续请求。
很显然:当滑动窗口的格子划分的越多,滑动窗口的滚动就越平滑,限流的统计就会越精确。
-
漏桶限流
漏桶算法的原理是按照固定常量速率流出请求,流入请求速率任意,当请求数超过桶的容量时,新的请求等待或者拒绝服务;可以看出漏桶算法可以强制限制数据的传输速度;
- 个人理解: 我们可以把发请求的动作比作成注水到桶中,我们处理请求的过程可以比喻为漏桶漏水。我们往桶中以任意速率流入水,以一定速率流出水。当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。如果想要实现这个算法的话也很简单,准备一个队列用来保存请求,然后我们定期从队列中拿请求来执行就好了。
-
令牌桶限流
令牌桶算法的原理是系统以一定速率向桶中放入令牌,填满了就丢弃令牌;请求来时会先从桶中取出令牌,如果能取到令牌,则可以继续完成请求,否则等待或者拒绝服务;令牌桶允许一定程度突发流量,只要有令牌就可以处理,支持一次拿多个令牌;
- 个人理解: 令牌桶算法也比较简单。和漏桶算法算法一样,我们的主角还是桶(这限流算法和桶过不去啊)。不过现在桶里装的是令牌了,请求在被处理之前需要拿到一个令牌,请求处理完毕之后将这个令牌丢弃(删除)。我们根据限流大小,按照一定的速率往桶里添加令牌。 具体基于以上算法如何实现,
提供了Guava
基于基于RateLimiter工具类
:令牌桶算法
- 以上代码表示一秒钟只允许处理五个并发请求,以上方式只能用在
的请求限流,不能进行单应用
。这个时候就需要全局限流
,可以基于分布式限流
来实现;redis+lua
- 个人理解: 令牌桶算法也比较简单。和漏桶算法算法一样,我们的主角还是桶(这限流算法和桶过不去啊)。不过现在桶里装的是令牌了,请求在被处理之前需要拿到一个令牌,请求处理完毕之后将这个令牌丢弃(删除)。我们根据限流大小,按照一定的速率往桶里添加令牌。 具体基于以上算法如何实现,
6.黑名单机制
如何为什么中黑我们这边不讨论,我们可以
给每个用户设置一个状态
比如包括:
初始化状态,正常状态,中黑状态,关闭状态
等等,或者我们直接通过
分布式配置中心
,
直接保存黑名单列表,每次检查是否在列表中即可
7.数据合法性校验
合法性校验包括:
常规性校验
以及
业务校验
- 常规性校验:包括签名校验,必填校验,长度校验,类型校验,格式校验等。
- 业务校验:根据实际业务而定,比如订单金额不能小于0等。
四.源码
优雅的实现第三方开放api接口签名(有状态/无状态)