目录
一、API
接口防篡改方案
1、API 接口暴露问题
由于提供给第三方服务调用的 API 接口需要暴露在外网中,并且接口上提供了具体的请求地址和请求参数,那么,接口就有可能被人抓包拦截并对请求参数进行修改后再次发起请求,这样一来可能会被盗取信息,二来服务器可能会受到攻击。
为了防止这种情况发生,需要采取安全机制措施进行防范,方法有多种,比如:
- 接口采用
https
的传输方式,https 传输的数据是经过了加密的,可以保证不被篡改(关于 https 的知识可以参考我的另一篇博客:【计算机网络】之 HTTPS 保证数据安全防止被篡改); - 项目后台采用安全的验证机制,比如采用参数加密和请求时间限制来防止参数篡改和二次投放(我们以这种方式为案例进行讲解)。
2、防止接口参数篡改
为了防止参数被抓包篡改参数,我们可以对参数进行加密。具体方式如下:
- 前端使用约定好的秘钥对传输参数进行加密,得到签名值 sign1,并且将签名值存入headers,然后发送请求给服务端;
- 服务端接收客户端的请求后,在过滤器中使用约定好的秘钥对请求的参数再次进行签名,得到签名值 sign2;
- 最后对比 sign1 和 sign2 的值,如果相同,则认定为合法请求,如果不同,则说明参数被篡改,认定为非法请求。
3、防止接口重投放
重投放或者叫二次投放,指的是接口被人拦截篡改参数后重新发送请求。防止重投放的方案是:基于 timestamp 对参数进行签名,具体的实现是:
- 每次 http 请求,headers 都加上 timestamp 时间戳,并且 timestamp 和请求的参数一起进行数字签名;
- 服务器收到请求之后,先判断时间戳参数与当前时间是否超过了60s(这个可以自定义配置,一般黑客从抓包到重放的耗时远远超过了60s),如果超过了则提示签名过期;
- 如果黑客修改了 timestamp 参数,则 sign 参数对应的数字签名就会失效,因为黑客不知道签名秘钥,没有办法生成新的数字签名(前端一定要保护好秘钥和加密算法)。
二、核心思路代码设计
代码思路主要是通过创建过滤器,对参数进行签名验证,核心过滤器代码如下:
@Component
@Slf4j
public class SignAuthFilter implements Filter {
@Autowired
private SignAuthProperties signAuthProperties;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("初始化 SignAuthFilter...");