接口请求安全措施
创始人
2025-06-01 19:57:48
0

一、敏感参数加密

一般情况下,我们针对一些敏感的参数,例如密码、身份证号等,给它加密,防止报文明文传输,加密可以分为大体的两类,对称加密和非对称加密,下面,简单介绍下这两种方式。

1、对称加密

对称加密:加密使用的密钥和解密使用的密钥是同一个,例如sm4加密
在这里插入图片描述
这样的加密方式简单,只需要加解密双方都有密钥即可,但是这样很不安全,一旦密钥泄漏,数据就会被解密。

2、非对称加密

非对称加密:顾名思义,非对称加密就是加密使用一个密钥(一般称为公钥),解密使用另一个密钥(一般称为私钥),常见的算法有RSA算法、sm2算法
在这里插入图片描述
这种情况下,私钥一般由解密方独立保存,极大提高了数据的安全性。如果要对所有请求参数加密,推荐使用https请求,因为https请求原理上也是非对称加密实现的,这里不做过多赘述。

二、加签验签

我们对参数进行了加密,那么数据是否安全了呢?答案是否定的,因为我们只是保证了传入参数不被别人知道,但是我们的请求或响应是可以被篡改拦截的,那么,就需要引入新的方案,加签验签。

1、加签

加签:用Hash函数把原始报文生成报文摘要,然后用私钥对这个摘要进行加密,就得到这个报文对应的数字签名。一般情况下,客户端会将签名和原始报文一起发给服务端。
在这里插入图片描述
客户端加签

//accessKey理解为一个盐值,signPriKey是加密私钥,map是请求参数
public static String sign(String accessKey, String signPriKey, Map map) {//sort方法主要用于参数排序及过滤,过滤掉key为sign的参数String paramStr = ParamSort.sort(map);//生成的摘要String abstractText = SM3Digest.sm3Encry(paramStr + accessKey);//非对称加密生成签名return SMHelper.sm2Sign(signPriKey, abstractText);}

获取摘要的hash方法

public static String sort(String jsonString){JSONObject jsonObject = JSON.parseObject(jsonString);String aa = jsonObject.toJSONString();List list = new ArrayList();for(Entry entry : jsonObject.entrySet()){String key = entry.getKey();//主要关注这里,排除了sign参数,因为sign签也是要作为参数传递给服务端的,但是客户端加签时还没有sign签if ("sign".equals(key)){continue;}String value = null;if (entry.getValue() instanceof JSONObject || entry.getValue() instanceof JSONArray){value = JSON.toJSONString(entry.getValue());} else {value = (String)entry.getValue();}String str = key+value;list.add(str);}Collections.sort(list, new Comparator() {@Overridepublic int compare(String o1, String o2) {try {String s1 = new String(o1.toString().getBytes("UTF-8"), "ISO-8859-1");String s2 = new String(o2.toString().getBytes("UTF-8"), "ISO-8859-1");return s1.compareTo(s2);} catch (Exception e) {e.printStackTrace();}return 0;}});StringBuffer paramStr = new StringBuffer();for(String param : list){paramStr.append(param);}return paramStr.toString();}

获取到sign签后,记得传递给服务端的参数加上sign签

map.put("sign",sign);

2、验签

验签:接收方拿到原始报文和sign签名后,用同一个Hash函数从报文中生成服务端摘要。然后用对方提供的公钥对数字签名进行解密,得到客户端摘要,对比两个摘要是否相同,就可以得知报文有没有被篡改过。
在这里插入图片描述
服务端验签

//ca是证书,存储了验签公钥等信息,sign是客户端的签名
private boolean sign(AuthSecCa ca, String sign, Map param) {//相同的排序hash方法String paramStr = Sort.sort(param);//生成服务端摘要String design = SM3Digest.SM3Encry(paramStr + ca.getAccessKey());// 验签boolean b = SMHelper.sm2Verify(ca.getSignPubKey(), design, sign);return b;}

三、请求时间戳验证

上面我们做了数据加密和请求加签验签,可以防止请求被抓包之后篡改请求,但是如果攻击者只是拦截数据包之后恶意请求怎么办呢?答案就是增加时间戳验证。大体思路就是请求参数加上一个请求时间戳dataStamp,服务端获取到这个时间戳后,获取一个当前的时间戳serverStamp,然后这两个时间戳的差值少于多长时间才算有效请求。

private boolean verifyDataStamp(String time) {boolean flag = false;long nowTime = System.currentTimeMillis();if (StringUtils.isNotEmpty(time)) {long t = Long.parseLong(time);//时间间隔超过1分钟int stampInt = stamp;if (Math.abs(nowTime - t) > stampInt * 1000) {flag = true;}}return flag;}

四、随机数验证

上面虽然做了时间戳验证,但是还是有漏洞的,只要攻击者在对应的时间范围(例如上面的一分钟)内恶意攻击还是能影响到我们的系统的,因此,我们需要给请求加上一个唯一的随机数nonce,每次请求过来把nonce拿到,判断是否已经又过了,来考虑是否放行请求,但是如果存储大量的nonce对我们的系统来说也是巨大的压力,因此配合时间戳一起使用,例如,时间戳是一分钟,我们可以设置nonce的有效期为两分钟(大于一分钟即可,避免极端情况),这样,我们把nonce存到缓存即可。

private boolean verifyNonce(String nonce) {if (StringUtils.isEmpty(nonce)) {return true;}if (缓存.isExist(nonce)) {return false;}缓存.setWithExpire(nonce, 120);return true;}

五、服务限流

这里介绍一个常见的限流算法,令牌桶限流。它的思路为:

  1. 对于每个要限流的对象(比如一个user,或者一个接入证书),分配一个bucket;
  2. bucket里的tokens以一个固定的速率在增加,bucket有个最大容量,到了最大容量就不再增加了;
  3. 每个请求会消耗一定的token数量,如果bucket内的token数量超过需要消耗的token数量,请求通过;否则拒绝请求;
    下面是通过引入guava的单机版限流RateLimiter做的一个限流demo
com.google.guavaguava31.1-jre

public class test {//每秒钟生成4个tokenprivate static final RateLimiter rateLimiter = RateLimiter.create(4);public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 10; i++) {new Thread(()->{//每次请求消耗一个tokenif(rateLimiter.tryAcquire()){System.out.println("请求成功");}else{System.out.println("限流了");}}).start();//每个请求相隔1/5秒Thread.sleep(200);}}
}

可以设想到每五个请求会有一个被限流,实际运行结果也是这样,这里的打印顺序和多线程的打印有关,并不是限流的问题
在这里插入图片描述

六、黑、白名单机制

我们可以在本身的后台管理系统中添加黑名单及白名单的相关配置,对于黑名单发起的请求,直接返回错误码;对于一些特别敏感的操作,例如涉及到转账等,只有在白名单中的请求才可以操作。

总结

前文提到了几种保证接口安全的措施,在实际项目应用过程中,可以将其串联起来使用,例如我们做一个全局的拦截器,拦截全部请求,然后在拦截器里将上述措施串联起来,用来保证接口请求的安全性。

相关内容

热门资讯

数字成语接龙 数字成语接龙精选  一尘不染 二龙戏珠 三生有幸 四分五裂 五光十色 六神无主 七嘴八舌 八面威风 ...
“铁钉铁铆”的意思 “铁钉铁铆”的意思 成语拼音: [tiě dīng tiě mǎo] ...
“情之所钟”的意思 “情之所钟”的意思 成语拼音: [qíng zhī suǒ zhōng] ...
“谦受益,满招损”的意思 “谦受益,满招损”的意思 成语拼音: [qiān shòu yì,mǎn zhāo sǔ...
“强唇劣嘴”的意思 “强唇劣嘴”的意思 成语拼音: [qiáng chún liè zuǐ] ...
“人云亦云”的意思 “人云亦云”的意思 成语拼音: [rén yún yì yún] ...
“变化无方”的意思 “变化无方”的意思 成语拼音: [biàn huà wú fāng] ...
“细高挑儿”的意思 “细高挑儿”的意思 成语拼音: [xì gāo tiǎo ér] ...
“分鞋破镜”的意思 “分鞋破镜”的意思 成语拼音: [fēn xié pò jìng] ...
“幺幺小丑”的意思 “幺幺小丑”的意思 成语拼音: [yāo mó xiǎo chǒu] ...
“谋臣武将”的意思 “谋臣武将”的意思 成语拼音: [móu chén wǔ jiàng] ...
“攒三集五”的意思 “攒三集五”的意思 成语拼音: [zǎn sān jí wǔ] ...
“虎视鹰瞵”的意思 “虎视鹰瞵”的意思 成语拼音: [hǔ shì yīng lín] ...
“逾淮为枳”的意思 “逾淮为枳”的意思 成语拼音: [yú huái wéi zhǐ] ...
“鸣珂锵玉”的意思 “鸣珂锵玉”的意思 成语拼音: [míng kē qiāng yù] ...
寻人启事 寻人启事范文(通用8篇)  寻人启事,汉语词语,发布寻人启事寻人,是失踪者及其亲友间相互寻找的一种基...
“乌合之卒”的意思 “乌合之卒”的意思 成语拼音: [wū hé zhī zú] ...
入木三分成语解释 入木三分成语解释  入木三分,是汉语的一则成语,出自唐·张怀瓘《书断·王羲之》。下面是小编为大家整理...
“逾闲荡检”的意思 “逾闲荡检”的意思 成语拼音: [yú xián dàng jiǎn] ...
形容勇敢的词语 形容勇敢的词语大全  词语,是词和短语的合称,包括词(含单词、合成词)和词组(又称短语),组成语句文...