diff --git a/docs/uniCloud/uni-id.md b/docs/uniCloud/uni-id.md index ef6f5ddc6cc5d95f913163f0421249c17f0b313c..4da2006b7ff2b6a85cdf2c5d9daa388efca7ddb4 100644 --- a/docs/uniCloud/uni-id.md +++ b/docs/uniCloud/uni-id.md @@ -1,52 +1,58 @@ -# 需求背景 +# 概述 -99%的应用,都要开发用户注册、登录、发送短信验证码、密码加密保存、修改密码、token管理等功能,从前端到后端都需要。 +99%的应用,都要开发用户注册、登录、发送短信验证码、修改密码、密码加密保存、密码防探测、token管理、注册用户统计等众多功能,从前端到后端都需要。 为什么不能有一个开源的通用项目,避免大家的重复开发呢? `uni-id`应需而生。 -`uni-id`为`uniCloud`开发者提供了简单、统一、可扩展的用户管理能力封装。 +`uni-id`为`uniCloud`开发者提供了开源、易用、安全、丰富、可扩展的用户管理框架。 [clientDB](uniCloud/clientDB)、[DB Schema](uniCloud/schema)、[uni-starter](https://ext.dcloud.net.cn/plugin?id=5057)、[uniCloud admin](uniCloud/admin),这些产品都基于`uni-id`的账户体系。可以说`uni-id`是uniCloud不可或缺的基础能力。 -# 组成部分 +## 组成部分 -`uni-id`包括如下组成部分: +`uni-id`是一个产品体系,前后台都有,包括: -1.云数据库 +1. 云数据库 -主表为 `uni-id-users` 表,保存用户的基本信息。扩展字段有很多,如实名认证数据、工作履历数据,开发者可以自由扩展。 +十几张用户相关的[opendb数据表](uniCloud/opendb),如[uni-id-users](https://gitee.com/dcloud/opendb/blob/master/collection/uni-id-users/collection.json)、[uni-id-roles](https://gitee.com/dcloud/opendb/blob/master/collection/uni-id-roles/collection.json)、[uni-id-permissions](https://gitee.com/dcloud/opendb/blob/master/collection/uni-id-permissions/collection.json)。 -还有 uni-id- 开头的十几个附表,比如权限表`uni-id-permissions`、角色表`uni-id-roles`、积分表`uni-id-scores`、设备表`uni-id-device`... +主表为 `uni-id-users` 表,保存用户的基本信息。扩展字段有很多,如实名认证数据、工作履历数据。由于MongoDB的特性,开发者可以自由扩展字段。 -所有`uni-id`的数据表,在uniCloud web控制台新建表的界面上,都可以选择这些数据表模板,直接建好。 +所有`uni-id`的数据表,不管在HBuilderX中新建DB Schema还是在uniCloud web控制台新建表的界面上,都可以选择模板直接建好。 -2.云函数 +2. 云端核心[公共模块](https://uniapp.dcloud.io/uniCloud/cf-common.html) [uni-id](https://ext.dcloud.net.cn/plugin?id=2116) -提供一个名为`uni-id`的公共模块,该模块封装了一系列API,包括注册、登录、修改密码、设置头像等。 +uni-id公共模块包含了账户体系服务端的核心代码,内置在每个uniCloud服务空间里。uniCloud众多功能(如DB Schema的权限)都依赖uni-id公共模块。 -示例工程中还提供了一个`user-center`的云函数,演示在云函数中如何调用`uni-id`公共模块。推荐使用[云端一体登录插件](https://ext.dcloud.net.cn/plugin?id=13) +包括注册、登录、修改密码、设置头像等各种操作,开发者无需直接操作uni-id-user表,调用公共模块的api接口即可。 -3.前端调用 +3. 云端一体页面模板 [uni-id-pages]() -前端示例通过callfunction调用云函数`user-center`,在注册和登录时保存token。在这个[云端一体登录插件](https://ext.dcloud.net.cn/plugin?id=13)里,有完整的登录、注册、修改密码等前后端代码示例。[详见](https://ext.dcloud.net.cn/plugin?id=13) +基于uni-id公共模块,DCloud还提供了一组完整的前端页面和后端[云对象](https://uniapp.dcloud.io/uniCloud/cloud-obj.html) `uni-id-co`,功能包括用户注册(含用户协议、隐私协议)、退出、修改密码、忘记密码等各种功能,同时适配PC宽屏和各种手机平台(App、H5、小程序)。 -uniCloud框架底层,会自动在callfunction时传递`uni-id`的token(uni-app 2.7.13+版本)。在云函数的event中可直接拿到`uni-id`的token。也就是说开发者无需自己管理token了。 +在云对象发布之前(HBuilderX 3.4以前),基于云函数方式,提供了uni-id-cf,功能类似。但在云对象上线后,推荐使用基于云对象的uni-id-pages,代码更简单清晰。 -# uni-id 对开发者的价值 +此外,DCloud的其他产品也为uni-id提供了众多支持: +- [uni-admin后台管理框架](https://uniapp.dcloud.io/uniCloud/admin.html),为uni-id提供了现成的用户、角色、权限的后台管理功能,以及注册用户统计报表。 +- uni-app框架内置的uniCloud客户端SDK,自动处理了uni-id的token的网络传输(uni-app 2.7.13+版本)、续期(uni-app 3. **待确认** +版本),也就是说开发者无需自己管理token了。 + +以上部分全部是开源的。 + +## uni-id 对开发者的价值 1. 节省了大量重复劳动 -2. 降低门槛,前端开发者无需纠结怎样设计数据库设计才更合理 +2. 降低门槛,前端开发者无需研究数据库如何设计、账户安全如何保障 3. 多系统打通用户和上下游协同 关于第三点,着重强调下。 -一个应用,往往需要集成多个功能模块。比如一个电商应用,需要一个基本电商模板,还需要客服聊天模板,甚至还需要用户交流社区。 +一个应用,往往需要集成多个功能模块。比如一个电商应用,需要一个基本电商模板,还需要客服聊天模板。 在插件市场,每类模板插件都能找到,但他们如果不是基于同一套用户体系设计,就很难整合。 -所有uniCloud的应用,几乎都基于`uni-id`来做。 +所有uniCloud的标准应用,都基于`uni-id`来做。`uni-id`公共模块自动内置在每个服务空间里的。 有了统一的账户规范,并且围绕这套账户规范,有各种各样插件,那么开发者可以随意整合这些插件,让数据连同。 @@ -54,28 +60,30 @@ uniCloud框架底层,会自动在callfunction时传递`uni-id`的token(uni-a 事实上,[clientDB](uniCloud/clientDB)、[DB Schema](uniCloud/schema)、[uni-starter](https://ext.dcloud.net.cn/plugin?id=5057)、[uniCloud admin](uniCloud/admin)等重要uniCloud产品,以及插件市场上各种优秀的轮子,都是基于`uni-id`的。 -# 现状和未来 +## 现状和未来 + +`uni-id`已完成的功能: + +- 注册、登录、发送短信验证码、密码加密保存、修改密码、重置密码、头像管理、token管理、rbac权限角色体系、用户邀请裂变、用户签到、日志记录、账户防刷 -`uni-id`已完成的内容: +关于登录方式,目前已实现 -- 注册、登录、发送短信验证码、密码加密保存、修改密码、token管理(短信验证码功能需要HBuilderX 2.8.3+) +- 账户密码登录 +- 手机号+短信验证码登录 - App手机号一键认证,免验证码 -- 三方登录:App中的微信登录和Apple ID、微信小程序中的微信登录、支付宝小程序中的支付宝账户登录 -- rbac权限角色体系 +- 三方登录:App中的微信登录和Apple ID登录、微信小程序中的微信登录、支付宝小程序中的支付宝账户登录 关于还缺少的部分,哪些DCloud在完善,哪些希望开发者给共同完善开源项目,计划与边界公布如下: -1.部分社交账户登录 +1. 无计划做的 -DCloud暂无计划开发百度、头条、QQ等小程序的登录,以及微博、QQ等App端的登录。欢迎其他开发者在开源项目上提交pr,共同完善`uni-id`。 +百度、QQ、快手、快应用等小程序的登录,以及微博、QQ等App端的登录。 -2.邮箱验证集成 +2. 有计划做但不是近期计划 -发送邮件验证邮箱真实性,DCloud暂无计划开发,有需求的开发者欢迎提供pr。 +web的微信扫码登录、字节小程序登录、facebook等海外主流社交账户登录、邮箱验证集成、活体检测。 -3.活体检测 - -目前插件市场里已经有不少相关插件,未来DCloud会整合到`uni-id`中。 +上述功能均欢迎其他开发者在开源项目上提交pr,或在插件市场发布插件,共同完善`uni-id`。 其他方面,各种常见开源项目如discuz、wordPress、ecshop的用户导入插件,不属于`uni-id`主工程,欢迎开发者单独提交插件到插件市场。 @@ -84,29 +92,40 @@ DCloud暂无计划开发百度、头条、QQ等小程序的登录,以及微博 # 快速上手@start -使用uni-id需要按照以下步骤操作 +uni-id公共模块的插件市场地址为:[uni-id公共模块](https://ext.dcloud.net.cn/plugin?id=2116)。但一般不需要单独下载这个插件,但更新uni-id公共模块时需要从这里下载更新。 + +一般推荐直接使用uni-starter项目模板来开始开发,或者在新项目里导入uni-id-pages页面模板来使用。 + +uni-id云端的配置是依赖[uni-config-center](/uniCloud/uni-config-center)公用模块的,在工程目录uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json。(如未安装uni-config-center需安装,如缺少目录需手动创建) + +uni-id云端同时依赖了公共模块[uni-captcha](https://ext.dcloud.net.cn/plugin?id=4048),这个功能模块负责生成和校验验证码,进行人机验证。 -**uni_modules版** +体验uni-id需保证uniCloud服务空间至少有数据表`uni-id-users`、`opendb-verify-codes`(验证码表) -1. HBuilderX 3.1.0+ -2. 插件市场导入`uni-id`公用模块uni_modules版本,HBuilderX会自动导入依赖的`uni-config-center`,[插件市场 uni-id](https://ext.dcloud.net.cn/plugin?id=2116) -3. 在`uni-config-center`公用模块下创建`uni-id`目录,在创建的uni-id目录下再创建`config.json`文件配置uni-id所需参数(请参考下面config.json的说明),**注意:如果HBuilderX版本低于3.1.8,批量上传云函数及公共模块后需要单独再上传一次uni-id** -4. 在`cloudfunctions/common`下上传`uni-config-center`模块以及`uni-id`模块 -5. 在要使用`uni-id`的云函数右键选择`管理公共模块依赖`添加`uni-id`到云函数,添加依赖后需要重新上传该云函数 -6. 创建`uni-id-users`、`opendb-verify-codes`集合(opendb-verify-codes是验证码表。可以使用示例项目里面的db_init.json进行初始化、也可以在web控制台新建表时选择这些表模块) +注意:如果HBuilderX版本低于3.1.8,批量上传云函数及公共模块后需要单独再上传一次uni-id -**非uni_modules版本(非uni_modules版本已不再更新)** +使用uni-id,首先需要确定2件事: -1. HBuilderX 2.9+ -2. 插件市场导入`uni-id`公用模块,[插件市场 uni-id](https://ext.dcloud.net.cn/plugin?id=2116) -3. 修改公用模块`uni-id`下的`config.json`内所需参数(请参考下面config.json的说明) -4. 上传`cloudfunctions/common`下的`uni-id`模块 -5. 按照[公用模块使用说明](/uniCloud/cf-common)在云函数下安装`uni-id`模块 -6. 创建`uni-id-users`、`opendb-verify-codes`集合(opendb-verify-codes是验证码表。可以使用示例项目里面的db_init.json进行初始化、也可以在web控制台新建表时选择这些表模块) +1. 确定注册登录方式 +你的应用采用什么方式注册登录?比如用户名密码、手机号+短信验证码、或者微信登录。 -或者直接导入[uni-id在插件市场的示例工程](https://ext.dcloud.net.cn/plugin?id=2116) +很多登录方式涉及三方服务,需要开通[短信验证码服务](uniCloud/send-sms)、开通[App一键登录](https://uniapp.dcloud.net.cn/univerify.html)、或者向微信等申请登录的appid和appsecret信息。 -## config.json的说明@config +申请开通相关服务后,需要把配置信息填写在云端配置文件config.json中。 + +2. 配置各项Secret + +账户如果涉及密码,那么需要配置`passwordSecret`,账户的密码会根据`passwordSecret`使用sha1摘要加密算法以不可逆的方式存储在数据库中。 + +配置`tokenSecret`是为了防止token被第三方解密,模拟用户身份。 + +千万不要使用默认的passwordSecret和tokenSecret,会造成系统安全隐患。 + +云端的config.json还有各种配置,详见下个章节。前端的配置请参考uni-id-pages的文档。 + +# 云端配置config.json的说明@config + +uni-id的云端配置文件在uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json中。 注意: @@ -282,10 +301,32 @@ uni-app vue2版本app端对应的platform为`app-plus`(HBuilderX 3.4.9起 vue2 } ``` +# token令牌 + +首先解释下token的概念。token是服务器颁发给客户端的一个令牌。 + +用户在客户端登录时,云端通过登录接口对用户的用户名+密码,或者手机号+验证码进行校验,校验通过后服务器会给客户端下发一个token(就是根据tokenSecret生成的一串加密字符串),并同时给出有效期。 + +客户端把这个token保存在storage中,然后每次联网请求服务器时,都带上这个token。服务器解密这个token,通过这个token认定客户端的身份。 + +这样就避免了客户端每次请求服务器,都需要再传输一次用户名和密码。 + +这是业内通行的设计。 + +在传统开发下,客户端和服务器各自需要为了token做很多事情。在uni云端一体下,开发者无需操心,只需要在uni-id云端config.json中配置好token的secret和有效期即可。剩余的工作都被自动处理了。 + +uni-id云端会在login方法成功后自动返回token,uni-app前端框架会自动识别并保存这个token在storage中(uni-id-token),在前端每次连接uniCloud(不管是clientDB、callfunction、云对象调用),都会自动带上这个token。 + +云函数和云对象都提供了获取和校验token的方法,在uni-id相关业务中,校验token的代码都已经写好。 + +包括token快到期时的自动续期,开发者只需在config.json中配置好临近多久自动续期,续期的代码也无法开发者编写,框架已经内置。 + +注:不同平台的token有效期一般不一样,app有效期较长,web有效期较短。每个平台的有效期都可以单独在config.json里配置。 + # 用户角色权限@rbac 为什么需要角色权限管理? -- 对于后台管理系统,比如[uniCloud admin](/uniCloud/admin),除了超级管理员,不同账号通常需根据职位、责任设定不同的系统权限。 +- 企业管理系统,比如[uniCloud admin](/uniCloud/admin),除了超级管理员,不同账号通常需根据职位、责任设定不同的系统权限。比如部门管理员、Hr。 - [clientDB](/uniCloud/database)允许前端直接操作数据库,但部分字段应该是系统计算或管理员设置的,比如文章的阅读数、收藏数及是否加精置顶,这些字段不允许普通用户在前端通过clientDB直接修改,此时也需要通过权限控制来保证系统的安全稳定。 `uni-id`基于经典的RBAC模型实现了角色权限系统。 @@ -301,20 +342,23 @@ RBAC:Role-Based Access Control,基于角色的访问控制。 这样做的好处是,增强系统管理的扩展性,对于批量用户的权限变更,仅需变更该批用户角色对应权限即可,而无需对该批每个用户变更权限。 这个模型有三个关键名词:用户、角色、权限: -- 用户:使用系统的人,一个用户可以同时有多个角色 -- 角色:权限的集合,一个角色可以有多个权限 -- 权限:数据权限或业务权限,例如:删除用户、删除评论等 +- 用户:使用系统的人,一个用户可以同时有多个角色,比如内容审核员、比如部门管理员 +- 角色:权限的集合,一个角色可以有多个权限。比如内容审核员这个角色,有隐藏帖子权限、有帖子加精权限;而部门管理员这个角色,有给本部门新增员工权限、有删除本部门员工的权限。 +- 权限:数据权限或业务权限,例如:删除用户、帖子加精等 + +用户、角色、权限都存在数据库了,都可以动态创建和修改。当权限对应的代码实现完成后,用户的新入、退出、角色升迁都无需再修改代码,在uni-admin后台的web界面可以由运维人员可视化的给每个用户调整角色、给每个角色调整权限。 ## 用户 用户信息存储在`uni-id-users`表中,然后通过`role`字段保存该用户所拥有的所有角色ID,角色ID即角色表(`uni-id-roles`表)中的`role_id`字段,注意不是`_id`字段。 -``` +``` json +// uni-id-users 表 { { "_id":"5f8428181c229600010389f6", - "username":"uniapp", - "email":"hr2013@dcloud.io", + "username":"张三", + "email":"zhangsan@dcloud.io", "role":[ "USER_ADMIN", "NOTICE_ADMIN" @@ -431,7 +475,7 @@ RBAC:Role-Based Access Control,基于角色的访问控制。 } ``` ->Tips1:建议出厂时内置所有权限,方便clientDB中的权限配置。 +>Tips1:建议代码交付时内置所有权限,方便clientDB中的权限配置和调整。 ## 其他说明 @@ -453,11 +497,197 @@ function hasPermission(token, permission) { 注意:**在uniCloud admin中,封装了可视化的用户、权限、角色的管理,新增删除修改均支持。**无需自己维护。[详见](https://uniapp.dcloud.net.cn/uniCloud/admin?id=mutiladmin) -**如果需要管理多端的用户,建议使用type在uni-id-users表内进行区分,不要分多个表** +# 数据库结构@db-schema + +`uni-id`的所有数据表,都在[opendb](https://gitee.com/dcloud/opendb/)规范中。 + +在unicloud [web控制台](https://unicloud.dcloud.net.cn/) 新建数据表时,可以从`uni-id`的模板分类里找到下面的表,并一键创建这些表。 + +## 用户表@user-table + +表名:`uni-id-users` + +| 字段 | 类型 | 必填 | 描述 | +| ---------------- | --------- | ---- | ------------------------------------------- | +| \_id | Object ID | 是 | 存储文档 ID(用户 ID),系统自动生成 | +| username | String | 否 | 用户名,不允许重复 | +| password | String | 否 | 密码。加密存储 | +| nickname | String | 否 | 用户昵称 | +| gender | Integer | 否 | 用户性别:0 未知 1 男性 2 女性 | +| role | Array | 否 | 用户角色列表,由role_id组成的数组 | +| status | Integer | 是 | 用户状态:0 正常,1 禁用,2 审核中,3 审核拒绝,4 已注销 | +| dcloud_appid | Array | 否 | 允许登录的客户端的appid列表,不同应用同时复用一个user表时适用,比如 司机端和乘客端是2个appid,在登陆时可以隔离,[详见](uniCloud/uni-id?id=isolate-user)| +| mobile | String | 否 | 手机号码 | +| mobile_confirmed | Integer | 否 | 手机号验证状态:0 未验证 1 已验证,未验证用户不可登录 | +| email | String | 否 | 邮箱地址 | +| email_confirmed | Integer | 否 | 邮箱验证状态:0 未验证 1 已验证,未验证用户不可登录 | +| avatar | String | 否 | 头像地址 | +| wx_unionid | String | 否 | 微信unionid | +| wx_openid | Object | 否 | 微信各个平台openid | +| ali_openid | String | 否 | 支付宝平台openid | +| apple_openid | String | 否 | 苹果登录openid +| comment | String | 否 | 备注 | +| realname_auth | Object | 否 | 实名认证信息 | +| register_date | Timestamp | 否 | 注册时间 | +| register_ip | String | 否 | 注册时 IP 地址,`uni-id 3.3.14`起移至register_env内 | +| last_login_date | Timestamp | 否 | 最后登录时间 | +| last_login_ip | String | 否 | 最后登录时 IP 地址 | +| login_ip_limit | Array | 否 | 登录 IP 限制 | +| inviter_uid | Array | 否 | 邀请人uid,按层级从下往上排列的uid数组,即第一个是直接上级| +| my_invite_code | String | 否 | 用户自己的邀请码 | +| register_env | Object | 否 | 用户注册时的环境信息,新增于`uni-id 3.3.14` | + +**注意** + +- 最后登录时间、IP,并非只有登录操作会修改,token刷新时也会修改最后登录时间、ip。应用启动时若token有效则不会触发登录行为,也不会更新本值。 + +**wx_openid字段定义** + +| 字段 | 类型 | 必填 | 描述 | +| ------- | ------| ---- | -------- | +| app-plus | String| 否 | app平台微信openid | +| mp-weixin | String| 否 | 微信小程序平台openid | +| h5-web | String| 否 | 微信网页应用openid | +| h5-weixin | String| 否 | 微信公众号应用openid | + +**realNameAuth 扩展字段定义** +该字段存储实名认证信息,子节点说明如下。 + +| 字段 | 类型 | 必填 | 描述 | +| --------------- | --------- | ---- | --------------------------------------------------- | +| type | Integer | 是 | 用户类型:0 个人用户 1 企业用户 | +| auth_status | Integer | 是 | 认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败 | +| auth_date | Timestamp | 否 | 认证通过时间 | +| real_name | String | 否 | 真实姓名/企业名称 | +| identity | String | 否 | 身份证号码/营业执照号码 | +| id_card_front | String | 否 | 身份证正面照 URL | +| id_card_back | String | 否 | 身份证反面照 URL | +| id_card_in_hand | String | 否 | 手持身份证照片 URL | +| license | String | 否 | 营业执照 URL | +| contact_person | String | 否 | 联系人姓名 | +| contact_mobile | String | 否 | 联系人手机号码 | +| contact_email | String | 否 | 联系人邮箱 | + +**job 扩展字段定义** + +| 字段 | 类型 | 必填 | 描述 | +| ------- | ------ | ---- | -------- | +| company | String | 否 | 公司名称 | +| title | String | 否 | 职位 | + +**register_env字段定义** + +**注意:调用addUser添加的用户无此字段** + +| 字段 | 类型 | 必填 | 描述 | +|-- |-- |-- |-- | +|appid |String|否 |注册时的客户端appId | +|uni_platform |String |否 |注册时的客户端平台,如h5、app、mp-weixin等 | +|os_name |String |否 |注册时的客户端系统名,ios、android、windows、mac、linux | +|app_name |String |否 |注册时的客户端名称 | +|app_version |String |否 |注册时的客户版本 | +|app_version_code |String |否 |注册时的客户版本号 | +|channel |String |否 |注册时的客户端启动场景(小程序)或应用渠道(app) | +|client_ip |String |否 |注册时的客户端IP | + + +用户集合示例: + +``` +{ + "_id": "f2a60d815ee1da3900823d45541bb162", + "username": "姓名" + "password": "503005d4dd16dd7771b2d0a47aaef927e9dba89e", + "status":0,//用户状态:0正常 1禁用 2审核中 3审核拒绝 + "mobile":"", + "mobile_confirmed":0, //手机号是否验证,0为未验证,1为已验证 + "email":"amdin@domain.com", + "email_confirmed":0, //邮箱是否验证,0为未验证,1为已验证 + "avatar":"https://cdn.domain.com/avatar.png" + "register_ip": "123.120.11.128", //注册IP + "last_login_ip": "123.120.11.128", //最后登录IP + +} +``` + +**如果需要管理多系统的用户,建议使用type在uni-id-users表内进行区分,不要分多个表** + +### 用户表索引使用注意@uni-id-users-indexes + +目前opendb内提供的uni-id-users表包含完整的索引,数据库在索引量多且频繁更新的情况下可能会出现写入缓慢的情况,因此推荐开发者在使用uni-id-users表时可以删除没有用到的索引。 + +例:项目内只使用了微信登录,不使用其他登录方式,可以只保留`wx_unionid、wx_openid.mp-weixin、wx_openid.app-plus`这些账号相关的索引,删除其他登录方式的索引(比如username、mobile) + +不了解索引请参考:[索引](/uniCloud/db-index.html) + +## 验证码表 + +表名:`opendb-verify-codes` + +**uni-id 2.0.0版本以前,使用的表名为uni-verify,2.0.0+起改为新表名** + +该表的前缀不是uni-id,意味着该表的设计用途是通用的,不管是uni-id的手机号验证码,或者支付等关键业务需要验证码,都使用此表。 + +每条验证信息,都记录在本表中。uni-id不会自动删除本表的历史数据,数据保留有效期需要开发者自行管理,可以在云函数中设置一个定时运行来清理过期数据。 + +| 字段 | 类型 | 必填 | 描述 | +| ---------- | --------- | ---- | -------------------------------------- | +| \_id | Object ID | 是 | 存储文档 ID(验证码 ID),系统自动生成 | +| mobile | String | 是 | 手机号,和邮箱二选一 | +| email | String | 是 | 邮箱,和手机号二选一 | +| code | String | 是 | 验证码 | +| type | String | 是 | 验证类型:login, bind, unbind, pay | +| state | Integer | 是 | 验证状态:0 未验证 1 已验证 2 已作废 | +| ip | String | 是 | 请求时 IP 地址 | +| created_at | Timestamp | 是 | 创建时间 | +| expired_at | Timestamp | 是 | 验证码过期时间 | + +## 角色表 + +表名:`uni-id-roles` + +| 字段 | 类型 | 必填| 描述 | +| ---------- | --------- | ----| --------------------------------------| +| \_id | Object ID | 是 | 系统自动生成的Id | +| role_id | String | 是 | 角色唯一标识 | +| role_name | String | 否 | 角色名,展示用 | +| permission | Array | 是 | 角色拥有的权限列表 | +| comment | String | 否 | 备注 | +| created_date| Timestamp | 是 | 角色创建时间 | + +## 权限表 + +表名:`uni-id-permissions` + +| 字段 | 类型 | 必填| 描述 | +| ---------- | --------- | ----| --------------------------------------| +| \_id | Object ID | 是 | 系统自动生成的Id | +| permission_id | String | 是 | 权限唯一标识 | +| permission_name | String | 否 | 权限名,展示用 | +| comment | String | 否 | 备注 | +| created_date | Timestamp | 是 | 权限创建时间 | + +## 更多表 + +还有更多uni-id的配套数据表,可以在uniCloud [web控制台](https://unicloud.dcloud.net.cn/)新建表时选择相应模板。此处不再详述,仅罗列清单: + +- 积分表:uni-id-scores +- 地址信息表:uni-id-address +- 订单表:uni-id-base-order +- 设备表:uni-id-device +- 关注粉丝表:uni-id-followers +- 日志表:uni-id-log +- 任务表:uni-id-task +- 任务日志表:uni-id-task-log + + +# uni-id公共模块的API列表@api + +`uni-id`公共模块提供了各种API,供云函数/云对象调用。 -# uni-id的API列表@api +一般开发者无需了解uni-id公共模块的API,直接使用[uni-id-pages]()即可(**需要补充链接**)。 -`uni-id`作为一个云函数的公共模块,暴露了各种API,供云函数调用。 +如果想了解uni-id公共模块内部实现,可以阅读本章节。 ## 基础功能@base @@ -3128,190 +3358,14 @@ const res = await uniID.forbidAppLogin({ 此接口会返回uni-id实例使用的配置内容。 -# 数据库结构@db-schema - -`uni-id`的所有数据表,都在[opendb](https://gitee.com/dcloud/opendb/)规范中。 - -在unicloud [web控制台](https://unicloud.dcloud.net.cn/) 新建数据表时,可以从`uni-id`的模板分类里找到下面的表,并一键创建这些表。 - -## 用户表@user-table - -表名:`uni-id-users` - -| 字段 | 类型 | 必填 | 描述 | -| ---------------- | --------- | ---- | ------------------------------------------- | -| \_id | Object ID | 是 | 存储文档 ID(用户 ID),系统自动生成 | -| username | String | 否 | 用户名,不允许重复 | -| password | String | 否 | 密码。加密存储 | -| nickname | String | 否 | 用户昵称 | -| gender | Integer | 否 | 用户性别:0 未知 1 男性 2 女性 | -| status | Integer | 是 | 用户状态:0 正常,1 禁用,2 审核中,3 审核拒绝,4 已注销 | -| mobile | String | 否 | 手机号码 | -| mobile_confirmed | Integer | 否 | 手机号验证状态:0 未验证 1 已验证,未验证用户不可登录 | -| email | String | 否 | 邮箱地址 | -| email_confirmed | Integer | 否 | 邮箱验证状态:0 未验证 1 已验证,未验证用户不可登录 | -| avatar | String | 否 | 头像地址 | -| wx_unionid | String | 否 | 微信unionid | -| wx_openid | Object | 否 | 微信各个平台openid | -| ali_openid | String | 否 | 支付宝平台openid | -| comment | String | 否 | 备注 | -| realname_auth | Object | 否 | 实名认证信息 | -| register_date | Timestamp | 否 | 注册时间 | -| register_ip | String | 否 | 注册时 IP 地址,`uni-id 3.3.14`起移至register_env内 | -| last_login_date | Timestamp | 否 | 最后登录时间 | -| last_login_ip | String | 否 | 最后登录时 IP 地址 | -| login_ip_limit | Array | 否 | 登录 IP 限制 | -| inviter_uid | Array | 否 | 邀请人uid,按层级从下往上排列的uid数组,即第一个是直接上级| -| my_invite_code | String | 否 | 用户自己的邀请码 | -| role | Array | 否 | 用户角色列表,由role_id组成的数组 | -| register_env | Object | 否 | 用户注册时的环境信息,新增于`uni-id 3.3.14` | - -**注意** -- 最后登录时间、IP,并非只有登录操作会修改,token刷新时也会修改最后登录时间、ip。应用启动时若token有效则不会触发登录行为,也不会更新本值。 +# 错误码@errcode -**wx_openid字段定义** +**自`uni-id 3.1.1`版本起使用此错误码规范** -| 字段 | 类型 | 必填 | 描述 | -| ------- | ------| ---- | -------- | -| app-plus | String| 否 | app平台微信openid | -| mp-weixin | String| 否 | 微信小程序平台openid | -| h5-web | String| 否 | 微信网页应用openid | -| h5-weixin | String| 否 | 微信公众号应用openid | +自`3.1.1`版本起uni-id使用errCode作为错误码,errMsg作为错误信息,符合[uniCloud响应体规范](/uniCloud/cf-functions.html#clientcallfunction)。为兼容旧版本,code、message字段仍保留。 -**realNameAuth 扩展字段定义** -该字段存储实名认证信息。 - -| 字段 | 类型 | 必填 | 描述 | -| --------------- | --------- | ---- | --------------------------------------------------- | -| type | Integer | 是 | 用户类型:0 个人用户 1 企业用户 | -| auth_status | Integer | 是 | 认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败 | -| auth_date | Timestamp | 否 | 认证通过时间 | -| real_name | String | 否 | 真实姓名/企业名称 | -| identity | String | 否 | 身份证号码/营业执照号码 | -| id_card_front | String | 否 | 身份证正面照 URL | -| id_card_back | String | 否 | 身份证反面照 URL | -| id_card_in_hand | String | 否 | 手持身份证照片 URL | -| license | String | 否 | 营业执照 URL | -| contact_person | String | 否 | 联系人姓名 | -| contact_mobile | String | 否 | 联系人手机号码 | -| contact_email | String | 否 | 联系人邮箱 | - -**job 扩展字段定义** - -| 字段 | 类型 | 必填 | 描述 | -| ------- | ------ | ---- | -------- | -| company | String | 否 | 公司名称 | -| title | String | 否 | 职位 | - -**register_env字段定义** - -**注意:调用addUser添加的用户无此字段** - -| 字段 | 类型 | 必填 | 描述 | -|-- |-- |-- |-- | -|appid | String|否 |注册时的客户端appId | -|uni_platform |String |否 |注册时的客户端平台,如h5、app、mp-weixin等 | -|os_name |String |否 |注册时的客户端系统名,ios、android、windows、mac、linux | -|app_name |String |否 |注册时的客户端名称 | -|app_version |String |否 |注册时的客户版本 | -|app_version_code |String |否 |注册时的客户版本号 | -|channel |String |否 |注册时的客户端启动场景(小程序)或应用渠道(app) | -|client_ip |String |否 |注册时的客户端IP | - - -用户集合示例: - -``` -{ - "_id": "f2a60d815ee1da3900823d45541bb162", - "username": "姓名" - "password": "503005d4dd16dd7771b2d0a47aaef927e9dba89e", - "status":0,//用户状态:0正常 1禁用 2审核中 3审核拒绝 - "mobile":"", - "mobile_confirmed":0, //手机号是否验证,0为未验证,1为已验证 - "email":"amdin@domain.com", - "email_confirmed":0, //邮箱是否验证,0为未验证,1为已验证 - "avatar":"https://cdn.domain.com/avatar.png" - "register_ip": "123.120.11.128", //注册IP - "last_login_ip": "123.120.11.128", //最后登录IP - -} -``` - -### 用户表索引@uni-id-users-indexes - -目前opendb内提供的uni-id-users表包含完整的索引,数据库在索引量多且频繁更新的情况下可能会出现写入缓慢的情况,因此推荐开发者在使用uni-id-users表时可以适当删除部分没有用到的索引。 - -例:项目内只使用了微信登录,不使用其他登录方式,可以只保留`wx_unionid、wx_openid.mp-weixin、wx_openid.app-plus`这些账号相关的索引,删除其他账号的索引 - -## 验证码表 - -表名:`opendb-verify-codes` - -**uni-id 2.0.0版本以前,使用的表名为uni-verify,2.0.0+起改为新表名** - -该表的前缀不是uni-id,意味着该表的设计用途是通用的,不管是uni-id的手机号验证码,或者支付等关键业务需要验证码,都使用此表。 - -每条验证信息,都记录在本表中。uni-id不会自动删除本表的历史数据,数据保留有效期需要开发者自行管理,可以在云函数中设置一个定时运行来清理过期数据。 - -| 字段 | 类型 | 必填 | 描述 | -| ---------- | --------- | ---- | -------------------------------------- | -| \_id | Object ID | 是 | 存储文档 ID(验证码 ID),系统自动生成 | -| mobile | String | 是 | 手机号,和邮箱二选一 | -| email | String | 是 | 邮箱,和手机号二选一 | -| code | String | 是 | 验证码 | -| type | String | 是 | 验证类型:login, bind, unbind, pay | -| state | Integer | 是 | 验证状态:0 未验证 1 已验证 2 已作废 | -| ip | String | 是 | 请求时 IP 地址 | -| created_at | Timestamp | 是 | 创建时间 | -| expired_at | Timestamp | 是 | 验证码过期时间 | - -## 角色表 - -表名:`uni-id-roles` - -| 字段 | 类型 | 必填| 描述 | -| ---------- | --------- | ----| --------------------------------------| -| \_id | Object ID | 是 | 系统自动生成的Id | -| role_id | String | 是 | 角色唯一标识 | -| role_name | String | 否 | 角色名,展示用 | -| permission | Array | 是 | 角色拥有的权限列表 | -| comment | String | 否 | 备注 | -| created_date| Timestamp | 是 | 角色创建时间 | - -## 权限表 - -表名:`uni-id-permissions` - -| 字段 | 类型 | 必填| 描述 | -| ---------- | --------- | ----| --------------------------------------| -| \_id | Object ID | 是 | 系统自动生成的Id | -| permission_id | String | 是 | 权限唯一标识 | -| permission_name | String | 否 | 权限名,展示用 | -| comment | String | 否 | 备注 | -| created_date | Timestamp | 是 | 权限创建时间 | - -## 更多表 - -还有更多uni-id的配套数据表,可以在uniCloud [web控制台](https://unicloud.dcloud.net.cn/)新建表时选择相应模板。此处不再详述,仅罗列清单: - -- 积分表:uni-id-scores -- 地址信息表:uni-id-address -- 订单表:uni-id-base-order -- 设备表:uni-id-device -- 关注粉丝表:uni-id-followers -- 日志表:uni-id-log -- 任务表:uni-id-task -- 任务日志表:uni-id-task-log - -# 错误码@errcode - -**自`3.1.1`版本起使用此错误码规范** - -自`3.1.1`版本起uni-id使用errCode作为错误码,errMsg作为错误信息,为兼容旧版本,code、message字段仍保留。 - -errCode和errMsg对照表如下: +errCode和errMsg对照表如下: |错误码(errCode) |详细信息(errMsg) |说明 | |--- |--- |--- | @@ -3344,7 +3398,7 @@ errCode和errMsg对照表如下: |uni-id-role-not-exist |角色不存在 |角色不存在 | |uni-id-permission-not-exist |权限不存在 |权限不存在 | -**自`1.1.0`版本使用此错误码规范** +** 历史版本 即`1.1.0`只`3.1.1`之间的版本使用下表错误码规范** |模块 |模块码 |错误代码 |错误信息 | |:-: |:-: |:-: |:-: | @@ -3423,8 +3477,104 @@ errCode和errMsg对照表如下: **另外还有一些字符串类型的扩展错误码在各自接口的文档中展示,请不要直接使用`code>0`这种方式来判断是否有错误,建议使用`if(code){}`来判断是否有错误** +# 多个应用复用相同uni-id-user表 + +有些系统由多个子应用组成,且没有各自独立服务空间,而是需要共享一个服务空间。此时就涉及一个问题,多个应用注册的账户都在uni-id-user表中,如何有效隔离。 + +比如一个打车软件,有乘客端、司机端、管理端,都要注册账户。它们也都有自己的DCloud appID(manifest.json里第一个配置) + +uni-id-user表中有一个数组型字段`dcloud_appid`,可以存贮这个用户有权登陆哪个应用。 + +比如乘客端的appid是`__uni_111111`,司机端appid是`__uni_222222`,那么2个appid都存入`dcloud_appid`,即表示这个用户有权登录这2个应用。 + +## 隔离不同应用的用户@isolate-user + +uni-id 3.3.0版本起用户注册时会自动在用户表的记录内标记为注册应用对应的用户,如果没有单独授权登录其他应用的话则只能登录这个应用。即在乘客端应用注册的,默认只能在乘客端应用登录。 + +如何授权登录其他应用请参考:[授权、禁止用户在特定客户端应用登录](uniCloud/uni-id?id=authorize-app) + +需要注意的是客户端APPID信息是由端上传上来的,并非完全可信,尽量在入口处进行校验。例: + +```js +exports.main = async function(event, context){ + if(context.APPID !== '__UNI__xxx1') { + throw new Error('应用ID非法') + } +} +``` + +**DCloud Appid是一个很重要的配置,如无必要请勿随意更换。** + +> 不同端用户数据通过用户表的dcloud_appid字段隔离,同一个手机号、微信号也可以同时注册管理端和用户端,绑定账号同理。 + +**注意** + +- uni-id会自动在用户表每条用户记录插入`dcloud_appid`字段(此字段是一个数组,标识此用户可以在哪些端登录)。 +- 为兼容旧版本,针对没有dcloud_appid字段的用户,允许登录任意端。 +- 如果用户数据库记录中`dcloud_appid`字段是一个空数组,表示当前用户不能在任何客户端登录 +- 已有dcloud_appid的用户,如果使用相同的用户标识(用户名、邮箱、手机、微信等)+ 不同的DCloud Appid登录会被判定为不同的用户,如果此时数据库没有对应的记录,会报用户不存在的错误 + +## 隔离不同应用的配置@isolate-config + +> `uni-id 3.3.0`及以上版本 + +uni-id的config.json支持配置为数组,每项都是一个完整的配置,对不同的配置使用`dcloudAppid`字段进行区分(**此字段与项目内的manifest.json里面的DCloud AppId一致**),uni-id会自动根据客户端的appid来判断该使用哪套配置。如果使用云函数url化请参考:[云函数Url化时使用](uniCloud/uni-id?id=url) + +需要注意的是客户端APPID信息是由端上传上来的,并非完全可信,尽量在入口处进行校验。例: + +```js +exports.main = async function(event, context){ + if(context.APPID !== '__UNI__xxx1') { + throw new Error('应用ID非法') + } +} +``` + +**示例** + +> 数组每一项都是一个完整的配置文件,全部选项请参考:[uni-id 配置](uniCloud/uni-id?id=config) + +**注意:如果允许同一账号在不同端使用相同的账号+密码登录需要将不同端的passwordSecret设置成一样的** + +```js +[{ + "dcloudAppid": "__UNI__xxxx1", // 务必替换为对应项目manifest.json内的DCloud Appid + "isDefaultConfig": true, // 默认配置标记,未匹配到dcloudAppid的情况下使用默认配置 + "passwordSecret": "passwordSecret-demo", + "tokenSecret": "tokenSecret-demo", + "tokenExpiresIn": 7200, + "tokenExpiresThreshold": 600, + "app-plus": { + "tokenExpiresIn": 2592000, + "oauth": { + "weixin": { + "appid": "weixin appid", + "appsecret": "weixin appsecret" + } + } + } +}, { + "dcloudAppid": "__UNI__xxxx2", // 务必替换为对应项目manifest.json内的DCloud Appid + "passwordSecret": "passwordSecret-demo", + "tokenSecret": "tokenSecret-demo", + "tokenExpiresIn": 7200, + "tokenExpiresThreshold": 600, + "app-plus": { + "tokenExpiresIn": 2592000, + "oauth": { + "weixin": { + "appid": "weixin appid", + "appsecret": "weixin appsecret" + } + } + } +}] +``` + + # 其他功能 + ## 裂变@fission 自`1.1.2`版本起uni-id支持裂变功能,目前仅适用手机号+验证码方式注册可以填写邀请码(inviteCode)接受邀请。裂变相关API请参考[裂变API](uniCloud/uni-id.md?id=fission-api) @@ -3589,91 +3739,6 @@ module.exports = { uni-id会自动进行语言匹配,无需额外配置 -## 隔离不同端用户@isolate-user - -一个完整的项目,通常需要客户端、管理端等,但是不同端的用户在同一服务空间下使用uni-id会比较难处理。比如不同端需要不同的配置文件、登录接口需要开发者自行隔离开。自`uni-id 3.3.0`起,支持对不同端用户进行隔离,此功能在此版本是直接开启的。 - -uni-id 3.3.0版本起用户注册时会自动在用户表的记录内标记为注册端用户,如果没有授权登录其他端的话是不可以在其他端登录的 - -如何授权登录其他端请参考:[授权、禁止用户在特定客户端登录](uniCloud/uni-id?id=authorize-app) - -需要注意的是客户端APPID信息是由端上传上来的,并非完全可信,尽量在入口处进行校验。例: - -```js -exports.main = async function(event, context){ - if(context.APPID !== '__UNI__xxx1') { - throw new Error('应用ID非法') - } -} -``` - -**DCloud Appid是一个很重要的配置,如无必要请勿随意更换。** - -> 不同端用户数据通过用户表的dcloud_appid字段隔离,同一个手机号、微信号也可以同时注册管理端和用户端,绑定账号同理。 - -**注意** - -- uni-id会自动在用户表每条用户记录插入`dcloud_appid`字段(此字段是一个数组,标识此用户可以在哪些端登录)。 -- 为兼容旧版本,针对没有dcloud_appid字段的用户,允许登录任意端。 -- 如果用户数据库记录中`dcloud_appid`字段是一个空数组,表示当前用户不能在任何客户端登录 -- 已有dcloud_appid的用户,如果使用相同的用户标识(用户名、邮箱、手机、微信等)+ 不同的DCloud Appid登录会被判定为不同的用户,如果此时数据库没有对应的记录,会报用户不存在的错误 - -## 隔离不同端配置@isolate-config - -> `uni-id 3.3.0`及以上版本 - -uni-id的config.json支持配置为数组,每项都是一个完整的配置,对不同的配置使用`dcloudAppid`字段进行区分(**此字段与项目内的manifest.json里面的DCloud AppId一致**),uni-id会自动根据客户端的appid来判断该使用哪套配置。如果使用云函数url化请参考:[云函数Url化时使用](uniCloud/uni-id?id=url) - -需要注意的是客户端APPID信息是由端上传上来的,并非完全可信,尽量在入口处进行校验。例: - -```js -exports.main = async function(event, context){ - if(context.APPID !== '__UNI__xxx1') { - throw new Error('应用ID非法') - } -} -``` - -**示例** - -> 数组每一项都是一个完整的配置文件,全部选项请参考:[uni-id 配置](uniCloud/uni-id?id=config) - -**注意:如果允许同一账号在不同端使用相同的账号+密码登录需要将不同端的passwordSecret设置成一样的** - -```js -[{ - "dcloudAppid": "__UNI__xxxx1", // 务必替换为对应项目manifest.json内的DCloud Appid - "isDefaultConfig": true, // 默认配置标记,未匹配到dcloudAppid的情况下使用默认配置 - "passwordSecret": "passwordSecret-demo", - "tokenSecret": "tokenSecret-demo", - "tokenExpiresIn": 7200, - "tokenExpiresThreshold": 600, - "app-plus": { - "tokenExpiresIn": 2592000, - "oauth": { - "weixin": { - "appid": "weixin appid", - "appsecret": "weixin appsecret" - } - } - } -}, { - "dcloudAppid": "__UNI__xxxx2", // 务必替换为对应项目manifest.json内的DCloud Appid - "passwordSecret": "passwordSecret-demo", - "tokenSecret": "tokenSecret-demo", - "tokenExpiresIn": 7200, - "tokenExpiresThreshold": 600, - "app-plus": { - "tokenExpiresIn": 2592000, - "oauth": { - "weixin": { - "appid": "weixin appid", - "appsecret": "weixin appsecret" - } - } - } -}] -``` ## 云函数Url化时使用@url