接口安全

数据是企业的重要资产,加强数据安全就是保护企业资产。

用户端调用前端接口(主要是数据库操作)是有安全风险的,开发者有责任管控接口以确保数据安全,不泄露给非授权用户。

要点

安全性

只有特定权限的用户才可执行特定操作,数据不被非授权用户篡改、删除,确保数据只在最小范围内可被操作。比如用户表数据只有管理员或用户本人才可以修改

机密性

只有特定权限的用户才可查看特定字段,不暴露给本不该看到数据的人,确保数据只在最小范围内可见。比如用户表里的手机号和身份证只有管理员或用户本人才能查看,其他人只能看到用户必要的非机密信息(昵称、头像等)

完整性

只有特定条件下才可执行特定操作,确保数据处于正确的状态、符合业务要求。比如生成会员编号有唯一性要求;再比如如果文章作者保存的是用户_id,删除了用户表中此作者的数据会导致无法显示作者姓名与头像。

并发性

多人在同一时刻同时更新同一数据时可能会破坏数据。比如给文章点赞时,如果是在客户端在当前文章点赞数的基础上加一后保存回数据库,那么在高并发状态下数据就会互相覆盖而让点赞数明显偏少。如果是在服务器端用$inc操作符来给点赞数加一就可以避免这种错误。

追溯性

记录数据操作历史记录可让数据改动可追踪,并具有不可抵赖性。类似于众触编辑器里的元数据的每次改动都记录着时间及其作者,可回滚到指定历史节点。开发者可根据需要酌情实现对业务表的追踪。

虽然平台在每个应用在创建时都预设了基础安全控制,但明显不够。进一步的控制就得依赖开发者根据具体业务场景来控制了。

开发者可以在设置中心的【后端服务】栏对每一个数据库API编写【执行前】表达式对其进行控制。这些表达式都在服务器环境中执行,如果表达式最后返回的值被判定为真将阻止api的执行。它有如下环境变量可用:

环境变量

API参数

比如$product.get(_id)里有_id变量,$product.search(path, query, option)里有path, query, option

user

即触发API的用户,里面最常用到的字段是_idrole。使用_id可进一步从数据库获取此用户相关数据;role是角色数组,常用来判断用户的权限。另外iatissued at的缩写,是用户身份标识(用户登录时)的签发时间(秒);expexpire的缩写,即用户身份标识的失效时间(秒),ai是用户所在的appId,提供跨站服务的时候作为验证用户来源的依据。

$x

如果当前API有_id参数时$x就是用此_id从数据库拿到的最新数据,比如get(),delete(),modify()。
数据$x保留着数据库中的类型,比如$x._id$x.auth是ObjectId类型,而非字符串,此时它与API参数_id进行比较时应避免使用===或!==,而应使用==!=来进行类型转换。

$exp

在“后端服务”栏编写的$exp表达式

isModifyY

当modify()接口会更改y里的字段时,isModifyY为真。

前端的绝大多数表达式也可用于后端,只能在前端环境中执行的就不能在后端执行了。比如$w、$()、$render()、localStorage()、load()、addClass()、info()、confirm()。log()之类的日志打印虽然调用了也不会报错,但它的打印结果是在后端控制台/日志里,前端看不到也就没有价值;想查看某个变量的值可以把它临时存入数据库。
比如想知道用户在登录多久后调用某API可用$xtk.modify("debug", "date-iat", { $push: date().getTime() / 1000 - user.iat }, 1),然后在前端(比如/db_admin页面里的数据库管理插件)取出来查看

此外还有两个专门为此设计的函数okIfngIf

条件检查

okIf(condition, fields, include)

符合就OK,不符就接着看
当条件condition成立允许当前用户执行该API而无需继续检查后续表达式。如果include-1时则表示要在返回结果中排除fields里的字段,否则只返回fields里指定的字段。如果无fields参数则返回所有数据。
当条件不成立时继续检查后续表达式。
注,search()是通过更改option参数里的select选项来指定
okIf(user.role.includes("admin") || $x.auth == user._id)
okIf(1, “x.姓名 wx.headimgurl“)   任何人都可以查看姓名和微信头像,但管理员或本人可查看所有字段

ngIf(condition, msgType, title, txt)

符合就NG,不符就接着看
当条件condition成立时拒绝当前用户执行该API而立即返回提示消息。msgType是消息类型,warn/error/info/alert/notify中的一个,title是消息标题,txt是消息文本(用于alert/notify)。
当条件不成立时继续检查后续表达式。
注:ng是Not Good的缩写
ngIf(!user.role.includes("admin") && $x.auth != user._id, “warn“, “未授权“, “你无权操作,请联系管理员“)

ngIfstopIf不同:stopIf仅仅是停止执行当前表达式块的后续表达式;而ngIf仅用在后端服务的执行前条件中,用来判断用户是否有权限执行此后端服务,所以它不仅停止执行后续表达式,更重要的是不再执行后端服务。

默认配置

平台提供基础的默认配置以快速保障基本安全,适合早期使用;后期需要进一步配置以满足复杂的业务安全需求。

由众触低代码平台生成和驱动