63.接口安全设计(活动管理系统:三)

news2024/12/27 0:24:02

文章目录

  • 一、参数校验
  • 二、统一封装返回值
  • 三、做权限控制
  • 四、加验证码
  • 五、 限流
  • 六、加ip白名单
  • 七、校验敏感词
  • 八、使用https协议
  • 九、数据加密
  • 十、做风险控制

在日常工作中,开发接口是必不可少的事情,无论是RPC接口还是HTTP接口,我们都应该考虑一个问题:如何保证接口的安全性呢?

常见保证接口安全的技巧如下:
在这里插入图片描述

一、参数校验

保证接口安全的第一步,也是最重要的一步,需要对接口的请求参数做校验。

如果我们把接口请求参数的校验做好了,可以拦截大部分的无效请求,节省了机器资源,也避免了程序报错。

通常我们可以按如下步骤做校验,当然,最重要的是根据具体的业务场景和诉求做校验

  1. 校验参数是否为空,有些接口中可能会包含多个参数,有些参数允许为空,有些参数不允许为空,我们需要对这些参数做校验,防止接口底层出现异常。
  2. 校验参数类型,比如:ageint类型的,用户传入了一个字符串:"123abc",这种情况参数不合法,需要被拦截。
  3. 校验参数的长度,特别是对于新增或者修改数据接口,必须要做参数长度的校验,否则超长了数据库会报异常。比如:数据库username字段长度是30,新用户注册时,输入了超过30个字符的名称,需要提示用户名称超长了。虽说前端会校验字段长度,但接口对参数长度的校验也必不可少。
  4. 校验枚举值,有些接口参数是枚举,比如:status,数据库中设计的该字段只有1、2、3三个值。如果用户传入了4,则需要提示用户参数错误。
  5. 校验数据范围,对于有些金额参数,需要校验数据范围,比如:单笔交易的money必须大于0,小于10000

二、统一封装返回值

对接口返回值统一封装是可以让代码更规范,也能使得接口更安全。

假如有这样一种场景:某个接口底层的sql,在某种条件下有语法问题。某个用户请求接口之后,在访问数据库时,直接报了sql语法错误,将数据库名、表名、字段名、相关sql语句都打印出来了。

此时,如果你的接口将这些异常信息直接返回给外网的用户,有些黑客拿着这些信息,将参数做一些调整,拼接一些注入sql,可以对你的数据库发起攻击。

因此,非常有必要对接口的返回值做统一的封装。

例如下面这样:

{
    "code":0,
    "message":null,
    "data":[{"id":123,"name":"abc"}]
}

json返回值中定义了三个字段:

  • code:表示响应码,0-成功,1-参数为空,2-参数错误,3-签名错误 4-请求超时 5-服务器内部错误等。工作中对于错误码的定义也有一定规范和技巧 ,如定义到同一个文件中,10001001,前四位1000表示业务,比如活动管理系统,1001表示具体错误 ,如参数校验失败
  • message:表示提示信息,如果请求成功,则返回空。如果请求失败,则返回我们专门在代码中处理过,让用户能看懂的错误信息。
  • data:表示具体的数据,返回的是一个json字段。

对返回值这样封装之后,即使在接口的底层出现了数据库的异常,也不会直接提示用户,而是内部判断错误后,给用户提示的是服务器内部错误。

注:工作中分为B端和C端两种服务场景

  • B端一般是内部使用的一些管理系统,这种系统对于报错应该返回给前端非常清晰明确的错误,这样产品和运营以及研发和测试等同事能很快知道出了什么错。
  • C端则是直接给外部用户使用的,我们不用给外部透露过多细节,出错时应该用一些兜底的页面或者策略,错误提示也应该是处理过不包含内部信息的,且能让用户能看得懂的信息,如服务器开小差啦,请稍后重试!,或者服务器内部错误、服务器繁忙等。

三、做权限控制

我们需要对接口做权限控制。主要包含了下面3种情况。

1、校验是否登录

  • 对于一些公共数据,比如:外部分类,所有人都能够看到,不用登录也能看到。对于这种接口,则不用校验登录。

  • 而对于有些查看内部分类的接口,需要用户登录之后,才能访问。这种情况就需要校验登录了。可以从当前用户上下文中获取用户信息,校验用户是否登录。如果用户登录了,当前用户上下文中该用户的信息不为空。否则,如果用户没登录,则当前用户上下文中该用户的信息为空。校验是否登录可以看本人之前相关博客:cookie、session、jwt等 44.jwt在go中的使用及原理

2、接口功能权限控制
对于有些重要的接口,比如订单审核接口,只有拥有订单审核权限的运营账号,才有权限访问该接口。对于一些后端原信息,如活动列表元信息,则需要校验读、写权限。

我们需要对该接口做功能权限控制,那么就应该有相应的权限记录信息,这里假设只关心管理员(可以授予别人读和写的权限)、读、写三个权限,则可以设计如下表,以活动管理系统为例

  • 在新建活动元信息的同时往权限表插入一条记录,通过事务保证元信息和权限两个表的SQL操作都成功。
  • 提供申请权限的接口,以及权限审批回调的接口,例如申请资源的读权限则接口应该创建一个审批流,审批通过后回调接口中则往如下权限表中插入一条记录。
  • 用户在操作相关资源前,便可以依据下表中的数据校验用户是否有对应的权限。
CREATE TABLE `resource_auth` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `resource_type` int NOT NULL DEFAULT '0' COMMENT '资源类型,如1:活动元信息   2:商品原信息  ...',
  `resource_id` bigint NOT NULL DEFAULT '0' COMMENT '资源id,resource_type=1时,resource_id=1就表示是id为1的活动元信息',
  `user_id` bigint NOT NULL DEFAULT '0' COMMENT '用户id,标识该用户对该资源的权限',
  `is_owner` int NOT NULL DEFAULT '0' COMMENT '当前用户是否owner权限,0:否,1:是',
  `is_reader` int NOT NULL DEFAULT '0' COMMENT '当前用户是否具有读权限,0:否,1:是',
  `is_writer` int NOT NULL DEFAULT '0' COMMENT '当前用户是否具有写权限,0:否,1:是',
  `created_at` datetime(3) DEFAULT NULL,
  `updated_at` datetime(3) DEFAULT NULL,
  `deleted_at` datetime(3) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

3、接口数据权限控制
对于有些订单查询接口,普通运营只能查看普通用户的数据。而运营经理可以查看普通用户和vip用户的数据。这种情况我们需要对该订单查询接口做数据权限控制。不同的角色,能够查看的数据范围不同。可以在查询数据时,在sql语句中动态拼接过滤数据权限的sql

四、加验证码

对于一些非常重要的接口,在做接口设计的时候,要考虑恶意用户刷接口的情况。最早的用户注册接口,是需要用图形验证码校验的,比如下面这样的:
在这里插入图片描述

用户只需要输入:账号名称、密码和验证码即可,完成注册。其中账号作为用户的唯一标识。但有些图形验证码比较简单,很容易被一些暴力破解工具破解。由此,要给图形验证码增加难度,增加一些干扰项,增加暴力破解工具的难度。

但有个问题是:如果图形验证码太复杂了,会对正常用户使用造成一点的困扰,增加了用户注册的成本,让用户注册功能的效果会大打折扣。因此,仅靠图形验证码,防止用户注册接口被刷,难道太大了。

后来,又出现了一些移动滑块或者选择图像形式的图形验证方式,安全性更高。
在这里插入图片描述

此外,使用验证码比较多的地方是发手机短信验证码的功能。

发手机短信的功能,一般是购买的云服务厂商的短信服务,按次收费,比如:发一条短信0.1元。如果发送短信的接口,不做限制,被用户恶意调用,可能会产生非常昂贵的费用。

五、 限流

上一节中提到的发送短信接口,只校验验证码还不够,还需要对用户请求做限流。从页面上的验证码,只能限制当前页面的不能重复发短信,但如果用户刷新了页面,也可以重新发短信。因此非常有必要在服务端,即:发送短信接口做限制。

我们可以增加一张短信发送表。该表包含:id、短信类型、短信内容、手机号、发送时间等字段。
在这里插入图片描述

有用户发送短信请求过来时:

  • 先查询该手机号最近一次发送短信的记录
  • 如果没有发送过,则发送短信。
  • 如果该手机号已经发送过短信,但发送时间跟当前时间比超过了60秒,则重新发送一条新的短信。
  • 如果发送时间跟当前时间比没超过60秒,则直接提示用户操作太频繁,请稍后重试。

这样就能非常有效的防止恶意用户刷短信的行为。

但还是有漏洞。

比如:用户知道在60秒以内,是没法重复发短信的。他有个程序,刚好每隔60秒发一条短信请求。这样1个手机号在一天内可以发:60*24 = 1440 条短信。如果他有100个手机号,那么一天也可以刷你很多条短信。由此,还需要限制每天同一个手机号可以发的短信次数。

其实可以用redis来做。

  • 用户发短信之后,在redis中保存一条记录,key是手机号,value是发短信的次数,过期时间是24小时。

  • 这样在发送短信之前,要先查询一下,当天发送短信的次数是否超过10次(假设同一个手机号一天最多允许发10条短信)。

  • 如果超过10次,则直接提示用户操作太频繁,请稍后重试。

  • 如果没超过10次,则发送短信,并且把redis中该手机号对应的value值加1

短信发送接口完整的校验流程如下:类似我们之前一篇频控发站内信的文章:26.redis实现日限流、周限流(含黑名单、白名单)
在这里插入图片描述
最后,我们之前也介绍过一些Go实现限流的方式:13. Go中常见限流算法示例代码,这种限流以及熔断降级等属于稳定性范畴,而非本文介绍的安全范畴。

六、加ip白名单

对于有些非常重要的基础性的接口,比如:会员系统的开通会员接口,业务系统可能会调用该接口开通会员。会员系统为了安全性考虑,在设计开通会员接口的时候,可能会加一个ip白名单,对非法的服务器请求进行拦截。这种动态名单方式,很像我们之前介绍的 17. 灰度开关、降级开关、灰度放量

这个ip白名单前期可以做成一个动态配置,如配置到zookeeper中,可以动态生效。如果后期ip数量多了的话,可以直接保存到数据库。

  • 只有ip在白名单中的那些服务器,才允许调用开通会员接口。

  • 这样即使开通会员接口地址和请求参数被泄露了,调用者的ip不在白名单上,请求开通会员接口会直接失败。

  • 除非调用者登录到了某一个白名单ip的对应的服务器,这种情况极少,因为一般运维会设置对访问器访问的防火墙。

  • 当然如果用了Fegin这种走内部域名的方式访问接口,可以不用设置ip白名单,内部域名只有在公司的内部服务器之间访问,外面的用户根本访问不了。

但对于一些第三方平台的接口,他们更多的是通过设置ip白名单的方式保证接口的安全性。

七、校验敏感词

对于某些用户可以自定义内容的接口,还需要对用户输入的内容做敏感词校验。

比如:在创建商品页面,用户输入了:傻逼商品,结果直接显示到了商城的商品列表页面,这种情况肯定是不被允许的。当然也可以做一个审核功能,对用户创建的商品信息做人工审核,如果商品数量太多,这样会浪费很多人力。

有个比较好的做法是:对用户自定义的内容,做敏感词校验。

  • 可以调用第三方平台的接口,也可以自己实现一个敏感词校验接口。

  • 可以在GitHub上下载一个开源的敏感词库,将那些敏感词导入到数据库中。

  • 然后使用hanlp对用户输入的内容,进行分词。对分好的词,去匹配敏感词库中的那些敏感词。

  • 如果匹配上了,则说明是敏感词,则验证不通过。

  • 如果没有匹配上,则说明非敏感词,则验证通过。

不可能在每个业务接口中都调用敏感词校验接口,我们可以定义中间件,在调用业务接口之前,先调用中间件,校验标记了需要校验敏感词的那些字段,将他们里面包含的内容,作为入参传入敏感词校验接口做校验。行为型之职责链模式

当然有时候hanlp分词器会把句子分错词,还需要添加一个敏感词的白名单,白名单中的词不是敏感词。

八、使用https协议

以前很多接口使用的是HTTP(HyperText Transport Protocol,即超文本传输协议)协议,它用于传输客户端和服务器端的数据。虽说HTTP使用很简单也很方便,但却存在以下3个致命问题:

  • 使用明文通讯,内容容易被窃听。
  • 不验证通讯方的真实身份,容易遭到伪装。
  • 无法证明报文的完整性,报文很容易被篡改。

为了解决HTTP协议的这些问题,出现了HTTPS协议。HTTPS协议是在HTTP协议的基础上,添加了加密机制:

  • SSL:它是Secure Socket Layer的缩写, 表示安全套接层。
  • TLS:它是Transport Layer Security的缩写,表示传输层安全。
  • HTTPS = HTTP + 加密 + 认证 + 完整性保护。

为了安全性考虑,我们的接口如果能使用HTTPS协议,尽量少使用HTTP协议。如果你访问过一些大厂的网站,会发现他们提供的接口,都是使用的HTTPS协议。不过需要注意的地方是:HTTPS协议需要申请证书,有些额外的费用。

九、数据加密

有些信息是用户的核心信息,比如:手机号、邮箱、密码、身份证、银行卡号等,不能被泄露出去。在保存到数据库时,我们要将这些字段,做加密处理。后面即使这些数据被泄露了,获得数据的人,由于没有密钥,没办法解密。

这种情况可以使用·AES对称加密·的方式,因为后面系统有些业务场景,需要把加密的数据解密出来。为了安全性考虑,我们需要设置一个用于加密的密钥,这个密钥可以稍微复杂一点,包含一些数字、字母和特殊字符。

  • 对于查询操作,需要做解密处理。

  • 对于写入操作,要做加密处理。

有些页面显示的地方,手机号一般不会显示完整的手机号,中间有一部分用*代替,比如:182***3457。这种情况需要做特殊处理。

十、做风险控制

有些特殊的接口,比如用户登录接口,我们需要对该接口做风险控制,尽可能减小被盗号的风险。

1、用户登录失败之后,需要有地方,比如:Redis,记录用户登录失败的次数。

  • 如果用户第一次输入账号密码登录时,出现的是一个稍微简单的验证码。
  • 如果用户把账号或密码连续输错3次之后,出现了更复杂的验证码。或者改成使用手机短信验证。
  • 如果用户在一天之内,把账号或密码连续输错10次,则直接锁定该账号。

这样处理是为了防止有人用一些软件,暴力破解账号和密码。

2、在用户登录成功之后,需要有一张表记录用户的ip、所在城市和登录的设备id。

如果你的账号被盗了。在盗号者在页面输入账号密码登录,会调用登录接口,此时登录接口中可以根据用户的ip和设备id,做一些风险控制。接口判断如果用户当前登录的ip、所在城市和设备ip,跟上一次登录成功时记录的相差非常大。

比如:1小时之前,用的ip100.101.101.101,城市是北京,设备id1001,而1小时之后,用的ip200.202.202.101,城市是广州,设备id2002。这种情况用户的账号极有可能被盗了。

3、登录接口做安全性升级,需要校验用户手机验证码才能登录成功。

由于盗号者只有你的账号和密码,没有手机验证码,所以即使被盗号了,也没办法登录成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1362566.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

opencv007 图像运算——加减乘除

今天学习图像处理的基础——加减乘除,总体来说比较好理解,不过生成的图片千奇百怪哈哈哈哈 opencv中图像的运算本质是矩阵的运算 加法 做加法之前要求两张图片形状,长宽,通道数完全一致 cv2.add(img1, img2) add的规则是两个图…

【算法笔记】深入理解dfs(两道dp题)

DFS过程的概述 一个一个节点的搜,如果是树状结构的话,先找到最左边那一条分支搜到最后一个节点,这个时候最后一个节点(假设是b)的数据会被更新(具体看题目的要求),然后返回到上一个…

debug mccl 02 —— 环境搭建及初步调试

1, 搭建nccl 调试环境 下载 nccl 源代码 git clone --recursive https://github.com/NVIDIA/nccl.git 只debug host代码,故将设备代码的编译标志改成 -O3 (base) hipperhipper-G21:~/let_debug_nccl/nccl$ git diff diff --git a/makefiles/common.mk b/makefiles/…

TypeScript接口、对象

目录 1、TypeScript 接口 1.1、实例 1.2、联合类型和接口 1.3、接口和数组 1.4、接口和继承 1.5、单继承实例 1.6、多继承实例 2、TypeScript 对象 2.2、对象实例 2.3、TypeScript类型模板 2.4、鸭子类型(Duck typing) 1、TypeScript 接口 接口…

rust sqlx包(数据库相关)使用方法+问题解决

可以操作pgsql、mysql、mssql、sqlite 异步的,性能应该不错,具体使用有几个坑 除了sqlx库,还有对于具体数据库的库,比如postgres库 演示以pgsql为例,更新时间2024.1.6 官方github: sqlx github rust官方文档&#xff1…

C++ Qt开发:Charts与数据库组件联动

Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍Charts组件与QSql数据库组件的常用方法及灵活…

【深度学习】cv领域中各种loss损失介绍

文章目录 前言一、均方误差二、交叉熵损失三、二元交叉熵损失四、Smooth L1 Loss五、IOU系列的loss 前言 损失函数是度量模型的预测输出与真实标签之间的差异或误差,在深度学习算法中起着重要作用。具体作用: 1、目标优化:损失函数是优化算法…

Unable to connect to Redis server

报错内容: Exception in thread "main" org.redisson.client.RedisConnectionException: java.util.concurrent.ExecutionException: org.redisson.client.RedisConnectionException: Unable to connect to Redis server: 175.24.186.230/175.24.186.230…

C语言scanf()函数详解

目录 1. scanf()函数简介 1.1 函数原型 1.2 头文件 1.3 返回值 1.4 参数 2.格式说明符 3.输入格式控制 关于‘ * ’的例子 关于width域宽的例子 关于length长度修饰符的说明 4. 其他常见问题说明 4.1 scanf()函数连…

2024年【烟花爆竹经营单位主要负责人】考试题及烟花爆竹经营单位主要负责人考试资料

题库来源:安全生产模拟考试一点通公众号小程序 2024年【烟花爆竹经营单位主要负责人】考试题及烟花爆竹经营单位主要负责人考试资料,包含烟花爆竹经营单位主要负责人考试题答案和解析及烟花爆竹经营单位主要负责人考试资料练习。安全生产模拟考试一点通…

纹理贴图如何为游戏角色增添质感

在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 游戏角色的3D建模是位移贴图技术广泛应用的领域之一。通过位移贴图&a…

记录汇川:H5U与Fctory IO 测试1

主程序: 子程序: Fctory IO通讯配置如下 : H5U作服务器,Fctory IO作客户端 这里参考:HU5作服务器地址 实现的动作如下: H5U与Factory IO联动

华为MDC610接口说明

1、MDC610对外功能接口 2、1、MDC610硬件技术规格

数据库初始化脚本(用 truncate 命令一键清空某个数据库中全部数据表数据)

数据库初始化脚本(用 truncate 命令一键清空某个数据库中全部数据表数据) 1.执行下面的sql语句生成“清空数据库的sql脚本”2.执行“清空数据库的sql脚本” 在开发中,当数据表结构有变动或者数据库中有脏数据时,想要清空数据表中的…

Python中的@abstractmethod

abstractmethod 是 Python 中 abc 模块(Abstract Base Classes)提供的一个装饰器,用于声明抽象方法。抽象方法是指在抽象类中声明但没有提供具体实现的方法,而是由其子类提供具体实现。 使用 abstractmethod 装饰器可以使得子类在…

普通BUG

IDEA包折叠 如果自动紧凑包名,则有些时候创建新包或类的时候不能达到想要的摆放层级关系,此时右上角搜索按钮搜hide middle,关掉紧凑即可,然后既可以每层一个包不折叠. 效果: 20240105println输出多个参数 int a 10;int b 20;报错println是可以输出多个参数的,但不支持直接用…

C++中的new和delete

相关文章 C智能指针 文章目录 相关文章前言一、new 运算符1. operator new 函数的范围2. 在类中重载new运算符3. 分配失败 二、delete 运算符1. 内存泄露统计示例2. 在类中重载delete运算符 总结 前言 在C中,new和delete是用于动态内存管理的运算符,它们…

优势演员-评论家算法 A2C

优势演员-评论家算法 A2C 优势演员-评论家算法 A2C主要思想目标函数 优势演员-评论家算法 A2C 前置知识:演员-评论家算法:多智能体强化学习核心框架 主要思想 AC 网络结构: 策略网络 - 演员: 这个网络负责根据当前的状态选择动作。它输出的是…

更改ERPNEXT源

更改ERPNEXT源 一, 更改源 针对已经安装了erpnext的,需要更改源的情况: 1, 更改为官方默认源, 进入frapp-bench的目录, 然后执行: bench remote-reset-url frappe //重设frappe的源为官方github地址。 bench remote-reset-url…

如何使用免费的ZeroSSL证书保护您的网站

使用 ZeroSSL 在您的站点上轻松实施 SSL。我们的指南涵盖了免费证书设置,确保安全和加密的用户连接。 如今,保护您的网站不仅是一种建议,而且是一种必需品。这就是SSL证书发挥作用的地方。它们对用户浏览器和网站之间传输的数据进行加密&…