This document is applicable to uni-id 4.0.0 and above, and requires HBuilderX 3.5.0 and above. Please visit the old version documentation: uni-id 3.x.x documentation

# Requirements background

99% of applications require the development of user registration, login, sending SMS verification codes, password modification, password encryption and storage, password detection, token management, page access rights, registered user statistics and many other functions, which are required from the front end to the back end. .

Why can't there be an open source general project to avoid repeated development by everyone?

uni-id is on demand.

uni-id provides an open source, easy-to-use, secure, rich, and extensible user management framework for uniCloud developers.

clientDB, DB Schema, uni-starter, uni-admin, these products are based on the uni-id account system. It can be said that uni-id is an indispensable basic capability of uniCloud.

# uni-id value

  1. Save a lot of repetitive work
  2. Lowering the threshold, front-end developers do not need to study how to design databases and how to ensure account security
  3. Multiple systems connect users and upstream and downstream collaboration

Regarding the third point, I would like to emphasize it.

An application often needs to integrate multiple functional modules. For example, an e-commerce application requires a basic e-commerce template, as well as a customer service chat template and a statistical kanban template.

In the plugin market, every type of template plugin can be found, but if they are not designed based on the same user system, it is difficult to integrate.

All uniCloud standard applications are based on uni-id. The uni-id-common common module is automatically built into each service space.

With a unified account specification and various plug-ins around this set of account specifications, developers can integrate these plug-ins at will to allow data interoperability.

Specifications can also allow the upstream and downstream to fully cooperate. There will be various data migration plug-ins in the plug-in market, such as plug-ins that migrate users from discuz to uni-id. I believe that the industry chain around this specification will be very active.

At present, the various excellent uniCloud wheels on the plug-in market are almost all based on uni-id.

# Feature list

uni-id completed functions:

  • Registration, login, sending SMS verification code, password encryption and saving, password modification, forgetting password, avatar management, token management, rbac permission role system, page access permission routing control, user invitation fission, user check-in, log record, account anti-brush

Regarding the login method, it has been implemented

  • Account password login
  • Mobile phone number + SMS verification code login (built-in uniCloud SMS capability)
  • App mobile phone number one-key authentication, no verification code (built-in uni-app App one-key login capability)
  • Three-way login: WeChat login, Apple ID, QQ login in App; WeChat login in WeChat applet; Alipay account login in Alipay applet; QQ login in QQ applet

Due to many three-party logins, DCloud does not have the energy to implement all of them, leaving empty implementations in uni-id-co. Developers are welcome to supplement, submit PR or publish extension plug-ins to improve uni-id together. .

Follow-up plan: In the future, DCloud will have built-in WeChat scan code login and official account login, mailbox verification integration, Facebook and other overseas mainstream social account login, and live detection.

In other respects, the user-imported plugins of various common open source projects such as discuz, WordPress, and ecshop do not belong to the main project of uni-id. Developers are welcome to submit plugins to the plugin market separately.

# Composition structure

uni-id runs through all links from the uni-app front end to the uniCloud back end.

Module Description
Related APIs of the front-end uni-app framework uniIdRouter page routing, token management client API
Front-end page uni-id-pages Login, register, change password, forget password, personal center, change avatar and other front-end pages
Network transmission automatically manages user tokens Automatically save, renew tokens, network automatically transmit tokens
cloud cloud object uni-id-co cloud object matched with uni-id-pages, cloud part of related business
Cloud configuration uni-config-center Various configurations available under uni-config-center
Cloud public module uni-id-common Used for cloud function or cloud object integration, this module verifies token identity
User-related data tables of cloud database Various opendb data tables such as uni-id-users
uni-admin Admin management background, including user role rights management, registered user statistics
  1. uni-id related table of cloud database

The database is the core of a system, uni-id first normalizes more than a dozen user-related opendb data tables,

The four most important opendb tables are as follows:

The main table is the uni-id-users table, which stores the basic information of users. There are many extended fields, such as real-name authentication data and work history data. Due to the characteristics of MongoDB, developers can freely extend fields.

All uni-id data tables, whether you create a new DB Schema in HBuilderX or on the interface of creating a new table in the uniCloud web console, can be created directly by selecting a template.

  1. Cloud common module uni-id-common

The uni-id-common public module contains the core permissions and token management of the account system server, and is built into each uniCloud service space.

If developers need to verify the front-end user token in their own cloud functions/cloud objects, they need to refer to the uni-id-common public module.

Many functions of uniCloud (such as DB Schema permissions, uni-id-co) also rely on uni-id-common.

See details

  1. uni-id configuration under cloud uni-config-center

uni-id has many configurations in the cloud, such as password encryption key, SMS and WeChat login appsecret, etc. These configurations are stored in config.json in the uni-id directory under uni-config-center.

see below

  1. Client API The uni-app framework has built-in uni-id token management.

uni-app is paired with uniCloud and uses uni-id. After logging in, the token is automatically issued, the network transport layer automatically transmits the token (uni-app 2.7.13+ version), and the token will be automatically renewed when it is about to expire (uni-app 3.4.13 + version), which means that developers do not need to manage tokens themselves.

The uni-app client also has a number of built-in APIs related to uni-id:

  • uniIDHasRole: Determines whether the current user has a role. Details
  • uniIDHasPermission: Determine whether the current user has a certain permission. Details
  • uniCloud.getCurrentUserInfo(): The client obtains the current user information. Details
  1. Cloud integrated page template uni-id-pages (including uni-id-co)

Based on uni-id-common, DCloud also provides a complete set of front-end pages and back-end cloud objects, collectively called uni-id-pages.

The functions of uni-id-pages include: user registration (including user agreement, privacy agreement), exit, password modification, forgetting password and other functions, and adapt to PC widescreen and various mobile platforms (App, H5, applet) .

In addition, other DCloud products also provide numerous support for uni-id:

All of the above are open source.

Historical legacy

Before HBuilderX 3.5, DCloud provided a common module uni-id (note that it is not called uni-id-common) and an example cloud Function uni-id-cf (integrated in uni-starter and uni-admin).

The old public module uni-id is a large and comprehensive account management public module, which is too bulky to be referenced by other cloud functions. For example, a business cloud function needs to verify the user token, and the referenced uni-id public module also contains the code for forgetting the password, which is a waste of resources.

Before the release of cloud objects, DCloud provided uni-id-cf based on cloud functions. But after HBuilderX 3.5, it is recommended to use cloud object-based uni-id-pages, the code is simpler and clearer.

From HBuilder 3.5 onwards, both uni-id and uni-id-cf will be phased out and will no longer be updated. The old common module uni-id was disassembled into uni-id-common public module and uni-id-co cloud object.

uni-id-common is very compact, including only tokens and permissions, and is suitable for being referenced by all cloud functions.

uni-id-co is a more complete and standardized user-managed cloud object than uni-id-cf.

Old version upgrade guide, see details

# Quick start

The plugin market address of uni-id-common is: uni-id-common plugin. But generally you don't need to download this plugin separately, but you need to download the update from here when you update the uni-id-common public module.

It is generally recommended to use the uni-starter project template directly to start development, or import the uni-id-pages page template to use in a new project.

The configuration of the uni-id cloud depends on the uni-config-center public module, which is in the project directory uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json . (If uni-config-center is not installed, it needs to be installed, and if the directory is missing, it needs to be created manually)

The uni-id cloud also relies on the public module uni-captcha, which is responsible for generating and verifying verification codes for human-machine verification.

To experience uni-id, you need to ensure that the uniCloud service space has at least data tables uni-id-users, opendb-verify-codes (verification code table)

With uni-id, you first need to determine 2 things:

  1. Determine how to register and log in

How does your app register and log in? Such as username and password, mobile phone number + SMS verification code, or WeChat login.

Many login methods involve third-party services, and you need to activate SMS verification code service, activate [App one-click login] (univerify.md), or apply for the appid and appsecret information for login to WeChat.

After applying to activate related services, you need to fill in the configuration information in the cloud configuration file config.json.

  1. Configure each Secret

If the account involves a password, you need to configure passwordSecret, and the password of the account will be irreversibly stored in the database according to the passwordSecret using the sha1 digest encryption algorithm.

Configuring tokenSecret is to prevent the token from being decrypted by a third party and impersonate the user's identity.

Do not use the default passwordSecret and tokenSecret, which will cause system security risks.

There are also various configurations in config.json in the cloud, see the next chapter for details. For the configuration of the front end, please refer to the documentation of uni-id-pages.

# Cloud configuration config.json description

The cloud configuration file for uni-id is in uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json.

Notice:

  • config.json is a standard json file and does not support comments

Configuration item:

  • passwordSecret is the key used to encrypt the password storage
  • tokenSecret is the secret key needed to generate the token
  • tokenExpiresIn token expiration in seconds
  • passwordErrorLimit the number of retries for password errors, record the number of password errors by ip, and wait for passwordErrorRetryTime time before retrying after reaching the number of retries
  • passwordErrorRetryTime单位为秒
  • 如果使用sendSmsCode接口发送短信需要前往uniCloud控制台开通并充值,配置config.jsonservice字段,字段说明见下方示例
  • In addition, different configurations can be made according to the client platform, refer to the following example

All times in the configuration files below are in seconds

! ! ! important! ! ! passwordSecret and tokenSecret are very important, remember to keep them properly (do not directly use passwordSecret and tokenSecret in the following example). Modifying the passwordSecret will cause old users to be unable to log in with the password, and modifying the tokenSecret will invalidate all issued tokens. If you re-import uni-id, do not directly overwrite config.json related configuration

// If you copy this content, remember to remove the comment
{
  "passwordSecret": [
    {
      "type": "hmac-sha256",
      "version": 1
    }
  ], // 数据库中password字段是加密存储的,这里的passwordSecret即为加密密码所用的加密算法,详见[密码安全]
  "passwordStrength": "medium", // 密码强度,新增于 uni-id-pages 1.0.8版本,见下方说明
  "tokenSecret": "", // 生成token所用的密钥,注意修改为自己的,使用一个较长的字符串即可
  "requestAuthSecret": "", // URL化请求鉴权签名密钥
  "tokenExpiresIn": 7200, // 全平台token过期时间,未指定过期时间的平台会使用此值
  "tokenExpiresThreshold": 3600, // 新增于uni-id 1.1.7版本,checkToken时如果token有效期小于此值且在有效期内则自动获取新token,请注意将新token返回给前端保存(云对象会自动保存符合uniCloud响应体规范的响应内的新token),如果不配置此参数则不开启自动获取新token功能
  "maxTokenLength": 10, // 数据库用户记录token数组的最大长度,默认为10。新增于uni-id-common 1.0.16
  "passwordErrorLimit": 6, // 密码错误最大重试次数
  "passwordErrorRetryTime": 3600, // 密码错误重试次数超限之后的冻结时间
  "autoSetInviteCode": false, // 是否在用户注册时自动设置邀请码,默认不自动设置
  "forceInviteCode": false, // 是否强制用户注册时必填邀请码,默认为false
  "idCardCertifyLimit": 1, // 实名认证相关; 限制每个身份证可以绑定几个账号
  "realNameCertifyLimit": 5, // 实名认证相关; 限制用户每日认证次数,防止接口被刷
  "sensitiveInfoEncryptSecret": "", // 敏感信息加密密钥(长度为32位的字符串),如使用实名认证功能需配置此密钥
  "frvNeedAlivePhoto": false, // 实名认证相关;是否获取认证照片
  "userRegisterDefaultRole": [], // 用户注册时的默认角色
  "app": { // 如果你使用旧版本uni-id公共模块而不是uni-id-common这里可能配置的是app-plus,务必注意调整为app
    "tokenExpiresIn": 2592000,
    "tokenExpiresThreshold": 864000,
    "oauth": {
      // The appid and appsecret used for App WeChat login need to be obtained on the WeChat open platform. Note: it is not a public platform but an open platform
      "weixin": {
        "appid": "",
        "appsecret": ""
      },
      // The appid and appsecret used for App QQ login need to be obtained from the Tencent open platform. Note: it is not a public platform but an open platform
      "qq": {
        "appid": "",
        "appsecret": ""
      },
      "apple": { // 使用苹果登录时需要
        "bundleId": ""
      }
    }
  },
  "web": { // 如果你使用旧版本uni-id公共模块而不是uni-id-common这里可能配置的是h5,务必注意调整为web
    "tokenExpiresIn": 7200,
    "tokenExpiresThreshold": 3600,
    "oauth": {
      "weixin-h5": { // 微信公众号登录配置
        "appid": "",
        "appsecret": ""
      },
      "weixin-web": { // 微信PC页面扫码登录配置
        "appid": "",
        "appsecret": ""
      }
    }
  },
  "mp-weixin": {
    "tokenExpiresIn": 259200,
    "tokenExpiresThreshold": 86400,
    "oauth": {
      // The appid and appsecret used for WeChat applet login need to be obtained from the corresponding applet management console
      "weixin": {
        "appid": "",
        "appsecret": ""
      }
    }
  },
  "mp-qq": {
    "tokenExpiresIn": 259200,
    "tokenExpiresThreshold": 86400,
    "oauth": {
      // The appid and appsecret used for QQ applet login need to be obtained from the corresponding applet management console
      "qq": {
        "appid": "",
        "appsecret": ""
      }
    }
  },
  "mp-alipay": {
    "tokenExpiresIn": 259200,
    "tokenExpiresThreshold": 86400,
    "oauth": {
      // For the appid and privateKey used for Alipay applet login, please refer to the Alipay applet documentation to set or obtain, https://opendocs.alipay.com/open/291/105971#LDsXr
      "alipay": {
        "appid": "",
        "privateKey": "", // 私钥
        "keyType": "PKCS8" // 私钥类型,如果私钥类型不是PKCS8,需要填写此字段,否则会出现“error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag”错误
      }
    }
  },
  "service": {
    "sms": {
      "name": "", // 应用名称,对应短信模版的name
      "codeExpiresIn": 180, // 验证码过期时间,单位为秒,注意一定要是60的整数倍
      "smsKey": "", // 短信密钥key,开通短信服务处可以看到
      "smsSecret": "", // 短信密钥secret,开通短信服务处可以看到
      "scene": {
        "bind-mobile-by-sms": { // 对绑定手机号场景的配置,短信验证码场景值参考:https://uniapp.dcloud.net.cn/uniCloud/uni-id-summary.html#sms-scene
          "templateId": "", // 绑定手机号使用的短信验证码模板
          "codeExpiresIn": 240 // 绑定手机号验证码过期时间
        }
      }
    },
    "univerify": {
      "appid": "", // 当前应用的appid,使用云函数URL化,此项必须配置
      "apiKey": "", // apiKey 和 apiSecret 在开发者中心获取,开发者中心:https://dev.dcloud.net.cn/pages/uniLogin/index,文档:https://ask.dcloud.net.cn/article/37965
      "apiSecret": ""
    }
  }
}

# Password Strength

Added in uni-id-pages 1.0.8

The passwordStrength configuration item supports the following four built-in rules

{
  // Password must contain uppercase and lowercase letters, numbers and special symbols
  super: /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/,
  // Password must contain letters, numbers and special symbols
  strong: /^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/,
  // Password must be any combination of letters, numbers and special symbols
  medium: /^(?![0-9]+$)(?![a-zA-Z]+$)(?![~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]+$)[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/,
  // Password must contain letters and numbers
  weak: /^(?=.*[0-9])(?=.*[a-zA-Z])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{6,16}$/
}

Front-end pages within uni-id-co and uni-id-pages both support these four built-in rules

# Login method and configuration instructions

Login method Configuration and access method
用户名、手机号、邮箱+密码 配置passwordSecret即可
手机号+验证码 配置service.sms,在uniCloud控制台短信服务内获取配置信息:短信服务
One-key login with mobile phone number Configure service.univerify and get it in the one-key login service in the developer center: One-key login
WeChat applet login Configure mp-weixin.oauth.weixin and obtain it on the WeChat public platform: WeChat public platform
WeChat official account login Configure web.oauth.weixin-h5, and obtain it on WeChat official platform: WeChat official platform
Scan the QR code to log in on the WeChat PC page Configure web.oauth.weixin-web and obtain it on the WeChat open platform: WeChat Open Platform
WeChat APP login Configure app.oauth.weixin and obtain it on the WeChat open platform: WeChat open platform
QQ applet login Configure mp-qq.oauth.qq and obtain it on the QQ open platform: QQ open platform
QQ APP login Configure app.oauth.qq and get it in QQ Interconnection: QQ Interconnection
Alipay applet login Configure mp-alipay.oauth.alipay and obtain it on the Alipay open platform: Alipay Open Platform
Apple APP login Configure app.oauth.apple and configure it yourself in the Apple Developer Center: Apple Developer Center

# 用户注册时设置默认角色uni-id-pages 1.1.6+

默认情况下,用户注册后不会关联任何角色,如果需要用户在注册后关联角色,可以通过此配置项开启。

配置项userRegisterDefaultRole的值类型为Array,每个元素为角色ID(role_id), 例如:

{
  "userRegisterDefaultRole": ["user"]
}

# token令牌

注意

如需保持活跃客户端的登录状态,请勿将token有效期设置一个很大的值,具体如何实现请参考:保持客户端登录状态

First explain the concept of token. A token is a token issued by the server to the client.

When a user logs in on the client, the cloud verifies the user's username + password, or mobile phone number + verification code through the login interface. After the verification is passed, the server will issue a token to the client (that is, a string generated based on tokenSecret). encrypted string), and at the same time give an expiration date.

The client saves this token in the storage, and brings this token every time it requests the server online. The server decrypts this token and identifies the client's identity through this token.

This avoids the need for the client to transmit the username and password again every time the client requests the server.

This is a common design in the industry.

Under traditional development, the client and server each need to do a lot of things for the token. Under the integration of uni cloud, developers don't need to worry about it, they only need to configure the token's secret and validity period in the uni-id cloud config.json. The rest of the work is handled automatically.

The uni-id cloud will automatically return the token after the login method is successful, and the uni-app front-end framework will automatically identify and save the token in the storage (uni_id_token), and connect to uniCloud every time in the front-end (whether it is clientDB, callfunction, cloud object call) , will automatically bring this token.

Both cloud functions and cloud objects provide methods for obtaining and verifying tokens. In uni-id related services, the code for verifying tokens has been written.

包括token快到期时的自动续期,开发者只需在config.json中配置好临近多久自动续期,续期的代码也无需开发者编写,框架已经内置。

Note: The validity period of tokens on different platforms is generally different, the validity period of the app is longer, and the validity period of the web is shorter. The validity period for each platform can be configured individually in config.json.

# User role permissions

Why do you need role rights management?

  • Enterprise management systems, such as uni-admin, except for super administrators, different accounts usually need to set different system permissions according to their positions and responsibilities. Such as department manager, HR.
  • clientDB allows the front-end to directly operate the database, but some fields should be calculated by the system or set by the administrator, such as the number of articles read, the number of favorites, and whether they are added to the top. These fields do not allow ordinary users to use the front-end Modifying directly through clientDB also requires permission control to ensure the security and stability of the system.

uni-id implements a role permission system based on the classic RBAC model.

# RBAC Model Introduction

RBAC: Role-Based Access Control, role-based access control.

Its basic idea: various permissions for system operations are not directly granted to specific users, but a role set is established between the user set and the permission set. Each role corresponds to a corresponding set of permissions. Once a user is assigned the appropriate role, the user has all the permissions of that role.

The advantage of this is that it enhances the scalability of system management. For the permission changes of batch users, it is only necessary to change the permissions corresponding to the roles of the batch of users, without changing the permissions of each user in the batch.

This model has three key nouns: users, roles, and permissions:

  • User: The person who uses the system, a user can have multiple roles at the same time, such as content reviewer, such as department administrator
  • Role: a collection of permissions, a role can have multiple permissions. For example, the role of content reviewer has the permission to hide posts and refine posts; and the role of department administrator has the permission to add employees to the department and delete the employees of the department.
  • Permissions: data permissions or business permissions, such as: delete users, refine posts, etc.

Users, roles, and permissions all exist in the database, and can be dynamically created and modified. When the code corresponding to the permissions is implemented, the user's new entry, exit, and role promotion do not need to modify the code. The web interface in the uni-admin background can be visually adjusted by the operation and maintenance personnel for each user and each role. permissions.

# User

User information is stored in the uni-id-users table, and then all the role IDs owned by the user are saved through the role field. The role ID is the role_id in the role table (uni-id-roles table) field, note not the _id field.

// uni-id-users table
{
  {
    "_id":"5f8428181c229600010389f6",
    "username":"张三",
    "email":"zhangsan@dcloud.io",
    "role":[
      "USER_ADMIN",
      "NOTICE_ADMIN"
    ],
    "created_date":1602495783272
  }  
}

Tips: Design the user role as a field of the user table instead of creating a new user role association table: avoid the performance overhead of mongodb when querying across tables

# Role

Role information is stored in the uni-id-roles table

Fields Type Required Description
_id Object ID Yes System auto-generated ID
role_id String Yes Unique role ID
role_name String No Role name, for display
permission Array yes list of permissions the role has
comment String No Comment
created_date Timestamp yes role creation time

in:

  • role_id is a role flag, which is globally unique and can be used for permission control in clientDB. It is recommended to name it semantically, for example: USER_ADMIN means personnel management, NOTICE_ADMIN means announcement management
  • permission is an array type, which stores all the permission IDs owned by the role. The permission ID is the permission_id field in the permission table (uni-id-permissions table), note that it is not the _id field

The following is an example:

{
  {
    "_id":"5f8428181c229600010389f6",
    "role_id":"USER_ADMIN",
    "role_name":"人事管理",
    "permission":[
      "USER_ADD",
      "USER_EDIT",
      "USER_DEL"
    ],
    "created_date":1602495783272
  },
  {
    "_id":"5f842836d8daea0001906785",
    "role_id":"NOTICE_ADMIN",
    "role_name":"公告管理",
    "permission":[
      "NOTICE_ADD",
      "NOTICE_EDIT",
      "NOTICE_DEL"
    ],
    "created_date":1602495784372
  }  
}

The following is an example of role configuration in clientDB:

// uni-id-users.schema.json
{
  "permission": {
    "update":"doc._id == auth.uid || 'USER_ADMIN' in auth.role" //用户自己或人事管理员可执行用户表的.update操作
  } 
}

Tips1: admin in uni-id is the super administrator role, and uni-clientDB is also based on the same policy; if the user role contains admin, the user has all permissions on all data tables.

Tips2: Common roles can be built-in at the factory, or roles can be dynamically created by operators after going online.

# Permissions

Permission information is in the uni-id-permissions table, and the table structure is defined as follows:

Fields Type Required Description
_id Object ID Yes System auto-generated ID
permission_id String Yes Unique ID of permission
permission_name String No Permission name, for display
comment String No Comment
created_date Timestamp yes permission creation time

Among them, permission_id is a permission flag, which is globally unique and can be used for permission configuration in clientDB. It is recommended to name it semantically, for example: USER_DEL, BRANCH_ADD. The total number of permissions cannot exceed 500

The following is an example content:

{
  {
    "_id":"5f8428181c229600010389f6",
    "permission_id":"USER_EDIT",
    "permission_name":"修改用户",
    "created_date":1602495783272
  },
  {
    "_id":"5f842836d8daea0001906785",
    "permission_id":"USER_DEL",
    "permission_name":"删除用户",
    "created_date":1602495784372
  }  
}

The following is an example of the configuration of permissions in clientDB:

// uni-id-users.schema.json
{
  "permission": {
    "update":"doc._id == auth.uid || 'USER_EDIT' in auth.permission" //用户自己或有`USER_EDIT`权限的用户,可执行用户表的.update操作
  }
}

Tips1: It is recommended that all permissions are built in when the code is delivered to facilitate the configuration and adjustment of permissions in clientDB.

# other instructions

The uni-id caches the user's role permissions within the token. For details, refer to: Cache role permissions.

The following is a simple example of judging permissions by token:

// Simple permission check example
function hasPermission(token, permission) {
  const {
	  uid,
	  role,
	  permission
  } = await uniID.checkToken(token)
  return role.includes('admin') || checkTokenRes.permission.includes(permission) // admin用户的permission为空数组,但是拥有所有权限
}

Note: In uniCloud admin, the visual management of users, permissions, and roles is encapsulated. New additions, deletions, and modifications are all supported, and there is no need to maintain it yourself. See details

# uni-id data table

All data tables for uni-id are in the opendb specification.

When creating a new data table in unicloud web console, you can find the following tables from the template category of uni-id, and create these tables with one click. Since HBuilderX 3.4.11, new DB Schemas also have templates to choose from.

# User table

Store basic user information.

Table name: uni-id-users

Fields Type Required Description
_id Object ID Yes Stores the document ID (user ID), the system automatically generates
username String No Username, no duplicates allowed
password password No Password. Encrypted Storage
nickname String No User nickname
gender int No User gender: 0 unknown 1 male 2 female
role Array no list of user roles, an array of role_ids
status int yes user status: 0 normal, 1 disabled, 2 under review, 3 review rejected, 4 logged out
dcloud_appid Array No Appid list of clients allowed to log in. It is applicable when different applications reuse a user table at the same time. For example, the driver and the passenger are two appids, which can be isolated when logging in, [see below](#isolate -user)
mobile String No Mobile number
mobile_confirmed int No Mobile number verification status: 0 not verified 1 verified, unverified users cannot log in
email String No Email address
email_confirmed int No Email verification status: 0 not verified 1 verified, unverified users cannot log in
avatar String No Avatar address
wx_unionid String No WeChat unionid
wx_openid Object No The openid of each platform of WeChat. The substructure is detailed below
qq_unionid String No QQ unionid
qq_openid Object No The openid of each QQ platform. The substructure is detailed below
ali_openid String No Alipay platform openid
apple_openid String No Apple login openid
comment String No Comment
realname_auth Object No Real-name authentication information. The substructure is detailed below
register_date Timestamp No Registration Date
register_ip String No IP address when registering, moved to register_env from uni-id 3.3.14
last_login_date Timestamp No Last login time
last_login_ip String No IP address of last login
login_ip_limit Array No Login IP Limit
inviter_uid Array No The inviter uid, an array of uid arranged from bottom to top according to the level, that is, the first one is the direct superior
my_invite_code String No User's own invitation code
register_env Object no Environment information for user registration, added in uni-id 3.3.14. The substructure is detailed below

Notice

  • This table only lists some fields, the full field see details
  • The last login time and IP, not only the login operation will be modified, the last login time and IP will also be modified when the token is refreshed. When the application starts, if the token is valid, the login behavior will not be triggered, and this value will not be updated.

wx_openid field definition

The uni-id-users table 1.0.0 in opendb is adjusted to the following structure, and uni-id-co uses this standard. How to deal with old data, please refer to: Upgrade from uni-id to uni-id-co+uni-id-common

Fields Type Required Description
app String No app platform WeChat openid
mp String No WeChat applet platform openid
web String No WeChat web application openid
h5 String No WeChat public account application openid

qq_openid field definition

The uni-id-users table 1.0.0 in opendb is adjusted to the following structure, and uni-id-co uses this standard. How to deal with old data, please refer to: Upgrade from uni-id to uni-id-co+uni-id-common

Fields Type Required Description
app String No app platform QQ openid
mp String No QQ applet platform openid

realNameAuth extension field definition This field stores real-name authentication information, and the sub-nodes are described as follows.

Fields Type Required Description
type Integer Yes User type: 0 personal user 1 enterprise user
auth_status Integer Yes Authentication status: 0 Not authenticated 1 Waiting for authentication 2 Authentication passed 3 Authentication failed
auth_date Timestamp No Authentication passed time
real_name String No Real Name/Business Name
identity String No ID number/business license number
id_card_front String No ID card front photo URL
id_card_back String No ID card back photo URL
id_card_in_hand String No ID card photo URL
license String No Business License URL
contact_person String No Contact name
contact_mobile String No Contact phone number
contact_email String No Contact email

register_env field definition

Note: This field is the front-end environment information recorded when the user was registered in the front-end. If the user is added by the administrator by calling the addUser of the uni-id in the cloud, there is no such field

Fields Type Required Description
appid String No Client appId when registering
uni_platform String No The client platform when registering, such as h5, app, mp-weixin, etc.
os_name String No Client system name when registering, ios, android, windows, mac, linux
app_name String No Client name when registering
app_version String No Customer version at registration
app_version_code String No Customer version number at registration
channel String No Client startup scene (applet) or application channel (app) when registering
client_ip String No Client IP when registering

User collection example:

{
  "_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"
  "last_login_ip": "123.120.11.128", //最后登录IP

}

# User table index usage note

At present, the uni-id-users table provided in opendb contains a complete index. When the database has a large number of indexes and is frequently updated, the writing may be slow. Therefore, it is recommended that developers can use the uni-id-users table. Delete unused indexes.

Example: Only WeChat login is used in the project, and no other login methods are used. You can only keep the account-related indexes such as wx_unionid and wx_openid.mp, and delete the indexes of other login methods (such as username, mobile)

If you don't know about indexes, please refer to: index

# Verification code table

Table name: opendb-verify-codes

The prefix of the table is not uni-id, which means that the table is designed for general use. Whether it is the verification code of the mobile phone number of the uni-id, or the verification code required for key businesses such as payment, this table is used.

Each piece of verification information is recorded in this form. The uni-id will not automatically delete the historical data of this table. The data retention period needs to be managed by the developer. You can set a timed operation in the cloud function to clear the expired data.

Fields Type Required Description
_id Object ID Yes Stores the document ID (verification code ID), which is automatically generated by the system
mobile String Yes Mobile phone number or email address
email String Yes Email, or mobile phone number to choose one
code String yes verification code
scene String yes verification scene
state Integer Yes Validation status: 0 not validated 1 validated 2 voided
ip String Yes IP address when requesting
create_date Timestamp yes creation time
expired_date Timestamp Yes Verification code expiration time

# Role table

Table name: uni-id-roles

Fields Type Required Description
_id Object ID Yes System auto-generated ID
role_id String Yes Unique role ID
role_name String No Role name, for display
permission Array yes list of permissions the role has
comment String No Comment
created_date Timestamp yes role creation time

# Permissions table

Table name: uni-id-permissions

Fields Type Required Description
_id Object ID Yes System auto-generated ID
permission_id String Yes Unique ID of permission
permission_name String No Permission name, for display
comment String No Comment
created_date Timestamp yes permission creation time

# more tables

There are more uni-id supporting data tables, you can select the corresponding template when creating a new table in uniCloud web console. I won't go into details here, just a list:

  • log table: uni-id-log
  • Score table: uni-id-scores
  • Address information table: uni-id-address
  • Order table: uni-id-base-order
  • Device table: uni-id-device
  • Follow followers table: uni-id-followers
  • Task table: uni-id-task
  • Task log table: uni-id-task-log

# Constants

# User status

Corresponds to the status field of the uni-id-users table

value description
0 Normal state
1 Ban status
2 Under review
3 Audit failed
4 Logout Status

# log type

Corresponds to the type field of the uni-id-log table

value description
logout logout
login login
register register
reset-pwd Reset Password
bind-mobile Bind mobile phone
bind-weixin Bind WeChat account
bind-qq Bind QQ account
bind-apple Bind Apple Account
bind-alipay Bind Alipay account

# Mobile phone, email verification code use scene

Corresponds to the scene field of the opendb-verify-codes table SMS, email verification code related records

value description
login-by-sms SMS verification code login
reset-pwd-by-sms SMS verification code reset password
bind-mobile-by-sms SMS verification code binding mobile phone number
login-by-email Email verification code login
reset-pwd-by-email Email verification code reset password
set-pwd-by-sms Mobile phone verification code set login password

# Graphical captcha usage scenario

Corresponds to the scene field of the record related to the graphic verification code of the opendb-verify-codes table

value description
register Username and password registration
login-by-pwd Username/Mobile/Email+Password Login
login-by-sms SMS verification code login
reset-pwd-by-sms SMS verification code reset password
reset-pwd-by-email Email verification code reset password
send-sms-code Send SMS Verification Code
send-email-code Send Email Verification Code
bind-mobile-by-sms SMS verification code binding mobile phone number
set-pwd-by-sms Mobile phone verification code set login password

# uniIdRouter auto-route

Added in HBuilderX 3.5.0

uniIdRouter is a solution that runs on the front-end and controls the routing of front-end page access rights.

Most apps specify that certain pages require a login to access. In the past, developers needed to write a lot of code.

Now, you only need to configure the login page path, pages that need to be logged in to access and other information in the pages.json of the project, and the routing jump of the uni-app framework will automatically log in when the login status of the client is expired or not logged in Jump to the login page.

Combine the following code and comments to learn how to use uniIdRouter

{
	"pages": [
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "uni-app"
			},
			"needLogin": false // 当前页面是否需要登录才可以访问,此配置优先级高于uniIdRouter下的needLogin
		}, {
			"path": "pages/list/list",
			"style": {
				"navigationBarTitleText": "uni-app"
			},
			"needLogin": true
		}, {
			"path": "pages/detail/detail",
			"style": {
				"navigationBarTitleText": "uni-app"
			}
		}
	],
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	},
	"uniIdRouter": {
		"loginPage": "pages/index/index", // 登录页面路径
		"needLogin": [
			"pages/detail/.*" // 需要登录才可访问的页面列表,可以使用正则语法
		],
		"resToLogin": true // 自动解析云对象及clientDB的错误码,如果是客户端token不正确或token过期则自动跳转配置的登录页面,配置为false则关闭此行为,默认true
	}
}

The above code specifies the login page as the home page index, and then sets the list page and all pages in the detail directory to require login to access. Then when accessing the list page and the pages in the detail directory, if the client is not logged in or the login status is expired (that is, the uni_id_token is invalid), it will automatically jump to the index page to log in.

There are two uniCloud client APIs corresponding to this function, uniCloud.onNeedLogin() and uniCloud.offNeedLogin(). After the developer listens to the onNeedLogin event, the framework will no longer automatically jump to the login page, but It is handled by the developer in the onNeedLogin event. For details, please refer to: uniCloud.onNeedLogin

When automatically jumping to the login page, it will carry the uniIdRedirectUrl parameter, whose value is encodeURIComponent(${page before jumping (full page address including path and parameters)}), if you want the user to jump back to the previous page after logging in , which can be achieved using this parameter.

Here is a simple example of a login page jumping to a previously visited page:

pages/login/login.vue

<template>
	<view>
		<button @click="login">login</button>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				uniIdRedirectUrl: ''
			}
		},
		onLoad(options) {
			this.uniIdRedirectUrl = decodeURIComponent(options.uniIdRedirectUrl)
		},
		methods: {
			async login() {
				// ...Execute the login operation and jump to the page in the success callback
				if (this.uniIdRedirectUrl) {
					uni.redirectTo({
						url: this.uniIdRedirectUrl
					})
				}
			}
		}
	}
</script>

# Cloud object response triggers needLogin

When the cloud object throws the uni-id token expired or token invalid error code, it will trigger the client to automatically jump to the configured login page. The following code is a simple example

// todo cloud object
const uniIdCommon = require('uni-id-common')
module.exports = {
	_before(){
		this.uniIdCommon = uniIdCommon.createInstance({
			clientInfo: this.getClientInfo()
		})
	},
	addTodo(title) {
		const {
			errCode,
			errMsg,
			uid
		} = await this.uniIdCommon.checkToken(this.getUniIdToken())
		if(errCode) { // uni-id-common的checkToken接口可能返回`uni-id-token-expired`、`uni-id-check-token-failed`错误码,二者均会触发客户端跳转登陆页面
			return {
				errCode,
				errMsg
			}
		}
		// ...
	}
}

Client add-todo.vue

<template>
	<!-- omitted -->
</template>
<script>
	export default {
		data() {
			return {
			}
		},
		onLoad() {},
		methods: {
			async addTodo(title){
				const todo = uniCloud.importObject('todo')
				await todo.addTodo(title) // 调用addTodo时云端checkToken如果返回了token错误、token失效的错误码就会自动跳转到配置的登录页面
			}
		}
	}
</script>
<style>
</style>

Notice

  • The above logic will only take effect if there is a uniIdRouter node in pages.json. Since HBuilderX 3.5.0, creating an empty project template will automatically configure an empty uniIdRouter node
  • The bottom layer of uniIdRouter uses the interceptors of navigateTo, redirectTo, reLaunch, and switchTab to intercept page jumps. It will not intercept entering the home page. The web and app ends will intercept native tabbar clicks, and other ends will not intercept native tabbar clicks. Generally, the tabbar page does not automatically jump, but provides a login button in the page. For example, there is a shopping cart or personal center on the tabbar. After clicking the shopping cart, a prompt and a button will be placed inside the shopping cart page to inform the user that they need to log in. To determine whether the user is logged in on the page, use APIuniCloud.getCurrentUserInfo()

# Cloud error code

Error Code errCode Error Message errMsg Description
0 (Number) Success -
uni-id-token-expired Login status invalid, token has expired -
uni-id-check-token-failed token verification failed -
uni-id-account-exists 账户已存在 -
uni-id-account-not-exists 账户不存在 -
uni-id-account-not-exists-in-current-app The matched user cannot log in in the current app
uni-id-account-conflict User account conflict It may be caused by the developer manually updating the database, and it should not appear under normal circumstances
uni-id-account-banned This account has been banned -
uni-id-account-auditing This account is being audited -
uni-id-account-audit-failed This account audit failed -
uni-id-account-closed This account has been canceled -
uni-id-captcha-required Please enter the graphic captcha -
uni-id-password-error Incorrect username or password -
uni-id-invalid-username Invalid username -
uni-id-invalid-password Invalid password -
uni-id-invalid-mobile Invalid mobile phone number -
uni-id-invalid-email Invalid email address -
uni-id-invalid-nickname Invalid nickname -
uni-id-invalid-param Parameter error -
uni-id-param-required missing parameter -
uni-id-get-third-party-account-failed Failed to get third party account -
uni-id-get-third-party-user-info-failed Failed to get third party user info -
uni-id-mobile-verify-code-error Mobile phone verification code error or expired -
uni-id-email-verify-code-error Email verification code is wrong or expired -
uni-id-admin-exists Super administrator already exists -
uni-id-permission-error permission error -
uni-id-system-error system error -
uni-id-set-invite-code-failed Failed to set invite code -
uni-id-invalid-invite-code Invite code invalid -
uni-id-change-inviter-forbidden Forbidden to modify the inviter -
uni-id-bind-conflict This account (WeChat, QQ, mobile phone number, etc.) has been bound -

# Multiple applications reuse the same uni-id-user table

Some systems are composed of multiple sub-applications, and there is no independent service space, but a shared service space. At this point, there is a problem. The accounts registered by multiple applications are in the uni-id-user table, how to effectively isolate them.

For example, a taxi software has a passenger terminal, a driver terminal, and a management terminal, and an account must be registered. They also have their own DCloud appID (the first configuration in manifest.json)

There is an array field dcloud_appid in the uni-id-user table, which can store which application this user is authorized to log in to.

For example, the appid of the passenger side is __uni_111111, and the appid of the driver side is __uni_222222, then both appids are stored in dcloud_appid, which means that the user has the right to log in to these two applications.

# Isolate users of different applications

Since uni-id version 3.3.0, when a user registers, it will be automatically marked as the user corresponding to the registered application in the records of the user table. If there is no separate authorization to log in to other applications, you can only log in to this application. That is, if you register in the passenger terminal application, you can only log in in the passenger terminal application by default.

如何授权登录其他应用请参考:授权、禁止用户在特定客户端应用登录

It should be noted that the client APPID information is uploaded from the end, and is not completely trusted. Try to verify it at the entrance. example:

exports.main = async function(event, context){
  if(context.APPID !== '__UNI__xxx1') {
    throw new Error('应用ID非法')
  }
}

**DCloud Appid is a very important configuration, please do not change it if it is not necessary. **

The user data of different terminals is isolated by the dcloud_appid field of the user table. The same mobile phone number and WeChat account can also register the management terminal and the user terminal at the same time, and the same is true for binding accounts.

Notice

  • uni-id will automatically insert the dcloud_appid field into each user record in the user table (this field is an array, which identifies which end this user can log in).
  • In order to be compatible with the old data generated by the old version, users without the dcloud_appid field are allowed to log in to any terminal.
  • If the dcloud_appid field in the user database record is an empty array, it means the current user cannot log in on any client
  • For users who already have dcloud_appid, if they use the same user ID (username, email, mobile phone, WeChat, etc.) + different DCloud Appid to log in, they will be judged as different users. If there is no corresponding record in the database at this time, the user will be reported to the user. nonexistent error

# Isolate configuration of different applications

The config.json of uni-id supports the configuration as an array, and each item is a complete configuration. Use the dcloudAppid field to distinguish different configurations (*This field is consistent with the DCloud AppId in the manifest.json in the project *), uni-id will automatically determine which configuration to use based on the client's appid.

It should be noted that the client APPID information is uploaded from the end, and is not completely trusted. Try to verify it at the entrance. example:

exports.main = async function(event, context){
  if(context.APPID !== '__UNI__xxx1') {
    throw new Error('应用ID非法')
  }
}

Example

Each item in the array is a complete configuration file. For all options, please refer to: uni-id configuration

Note: If the same account is allowed to log in with the same account + password on different sides, you need to set the passwordSecret on different sides to the same

[{
  "dcloudAppid": "__UNI__xxxx1", // 务必替换为对应项目manifest.json内的DCloud Appid
  "isDefaultConfig": true, // 默认配置标记,未匹配到dcloudAppid的情况下使用默认配置
  "passwordSecret": "passwordSecret-demo",
  "tokenSecret": "tokenSecret-demo",
  "tokenExpiresIn": 7200,
  "tokenExpiresThreshold": 600
}, {
  "dcloudAppid": "__UNI__xxxx2", // 务必替换为对应项目manifest.json内的DCloud Appid
  "passwordSecret": "passwordSecret-demo",
  "tokenSecret": "tokenSecret-demo",
  "tokenExpiresIn": 7200,
  "tokenExpiresThreshold": 600
}]

# 其他功能

# token更新及保持客户端登录状态

一般来说token的有效期不会无限长,示例配置内web端token有效期为2小时,微信小程序为3天,app端为30天。你可以回忆一下你所用的软件,只要每天都打开就一直不需要重新登录,这样就牵扯到保持客户端的登录状态的问题。

uni-id使用了判断token剩余有效时间小于一定的阈值(配置文件内的tokenExpiresThreshold)但是大于0时自动下发新token的逻辑来保证活跃客户端一直处于登录状态,返回新token的逻辑由checkToken方法实现。具体该将token有效期和token刷新阈值设置为多少,需要根据多数用户软件使用频率来确定。

举个例子,开发者配置的token有效期(tokenExpiresIn)为1天,token刷新阈值(tokenExpiresThreshold)为8小时。用户在0点0分0秒获取了token,如果用户在16点后(token有效期已小于8小时)调用接口时执行了checkToken方法则会返回新token。

# fission

If autoSetInviteCode: true is configured in config.json (uniCloud/cloudfuntions/common/uni-config-center/uni-id/config.json, the following config.json refers to this file), the user registers It will automatically set a 6-digit invitation code that does not repeat

If forceInviteCode: true is configured in config.json, you can only register with an invitation code.

uni-id-co adds the inviteCode parameter to the interface that will generate the registration behavior, which is used to pass the invitation code to make the registered user accept the invitation

# Modify passwordSecret

Note: Usually, you do not need to modify the passwordSecret after setting it. Please be careful when using this function

illustrate

Modifying passwordSecret in config.json will prevent historical users from logging in with passwords. However, in some cases, some applications need to modify the passwordSecret. For example, when the uni-id is first used, the passwordSecret is not customized, and it needs to be modified later. In this case, you can use the new passwordSecret modification function of the uni-id version 2.0.1. (Note: The name of the verification code table in version 2.0.1 has been adjusted to opendb-verify-codes)

how to use

The following is an example of how to modify passwordSecret from passwordSecret-demo to qwertyasdfgh

// old config.json
{
  "passwordSecret": "passwordSecret-demo"
}

// new config.json
{
  "passwordSecret": [{
    "version": 1,
    "value": "passwordSecret-demo"
  },{
    "version": 2,
    "value": "qwertyasdfgh"
  }]
}

If you modify the passwordSecret to 1q2w3e4r5t on the basis of the above, config.json is adjusted as follows

!!! Note that only users who are not using a key of a certain version (the password_secret_version field indicates the user's secret version) in the database can remove this key from config.json. Users who do not have password_secret_version use the oldest version of the passwordSecret. If there is such a user, the corresponding passwordSecret cannot be removed.

// new config.json,
{
  "passwordSecret": [{
    "version": 1,
    "value": "passwordSecret-demo"
  },{
    "version": 2,
    "value": "qwertyasdfgh"
  },{
    "version": 3,
    "value": "1q2w3e4r5t"
  }]
}

principle

The password field stored in the uni-id-users table is a hash value generated by using hmac-sha1, which irreversibly deduces the user's real password. Therefore, directly modifying the passwordSecret will cause the old user to be unable to log in with the password.

The above modification distinguishes the old and new keys by the key version number. When the user logs in, if the key version is smaller than the current latest version, the password field stored in the database will be updated for the user, and the currently used key version will be recorded.

If there is no key version in the database record corresponding to the user, the lowest version key will be used for password verification. After the verification is passed, the user will be updated to the password corresponding to the latest version key and the version number will be recorded.

Since it is irreversible encryption, in theory, the leakage of the passwordSecret will not cause the user's real password to be leaked. Customizing the passwordSecret only further enhances the security.

# Cache role permission

When using uni-id-common, the user's role permissions are cached in the token.

Why cache role permissions in the token? Token verification is a high-frequency operation, ApsaraDB charges fees based on the number of reads and writes, and reading and writing the database will slow down the response speed of the interface.

A more economical approach is to cache role permissions in the token. A better solution is to cache role permissions in redis, but redis needs to be paid for.

Notice

  • Since the role permissions are cached in the token, there may be cases where the permissions have been updated but the user token is still the old version of the role permissions before it expires. The token expiration time can be shortened to reduce the impact of this situation. Or use redis to cache user permissions
  • The admin role token does not contain permission. If you need to determine whether the user has a certain permission, you should pay attention to the admin role. You need to make additional judgments. As long as the role is admin or the permission contains the expected value, it is regarded as having permission.

# Custom token content

uni-id-common supports caching the user's role permissions within the token. But in some cases developers may also want to cache something else for easy access on the client side (Note: do not cache confidential information in the token).

usage

Create custom-token.js in the uni-id plugin in the uni-config-center module with the following content:

module.exports = async (tokenObj) => { 
  // {
  // uid: 'abc', // user id
  // role: [], // list of user roles
  // }
  
  tokenObj.customField = 'hello custom token' // 自定义token字段
  return tokenObj // 注意务必返回修改后的token对象
}

uni-id will automatically load custom-token.js for processing, and automatically obtain new token information and generate tokens when all token-generating operations (including: login, registration, automatic token refresh after token expiration, and developers calling createToken by themselves) are executed.

Notice

  • don't delete the fields inside the original token

# Custom internationalization language

For a complete list of words and phrases:

  • [uni-id-co Chinese language pack](https://gitcode.net/dcloud/hello_uni-id-pages/-/blob/master/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id- co/lang/zh-hans.js)
  • uni-id-common Chinese language pack

usage

Create index.js in the cloudfunctions/common/uni-config-center/uni-id/lang/ directory, the content example is as follows:

module.exports = {
	'zh-hant': { // 语言代码
		'alipay': '支付寶'
	}
}

uni-id will automatically perform language matching without additional configuration

# Automatically save user sessionKey, accessToken and other information

uni-id-co will automatically save the user's sessionKey and accessToken information when logging in or registering on WeChat or QQ.

Before uni-id-pages 1.0.8, uni-id-co directly stored this information in the third_party field of the user table (uni-id-users), which was only distinguished by platform and not by different applications. The specific structure is as follows

{
  "_id": "uid",
  "wx_unionid": "xxx",
  "qq_unionid": "xxx",
  "third_party": {
    "mp_weixin": {
      "session_key": "xxxx"
    },
    "app_weixin": {
      "access_token": "accessToken",
      "access_token_expired": 1111
    },
    "mp_qq": {
      "session_key": "xxxx"
    },
    "app_qq": {
      "access_token": "accessToken",
      "access_token_expired": 1111
    }
  }
}

This structure cannot meet the scenario where multiple applications are associated with the same service space on the same platform and users are allowed to log in across applications. So in uni-id-pages 1.0.8 and later this was adjusted to use [uni-open-bridge-common](uni-open-bridge.md#uni-open-bridge- common) to store the user's credential information on the third-party platform. At the same time, this information still exists in the third_party field above for compatibility with older versions.

The three-party credentials currently saved by uni-id-co are as follows:

  • Wechat applet user session_key, written through the setSessionKey method of uni-open-bridge-common
  • Wechat official account page user access_token, written through the setUserAccessToken method of uni-open-bridge-common
  • The user access_token returned when the WeChat web page scans the code to log in, which is written through the setUserAccessToken method of uni-open-bridge-common
  • The user access_token returned by WeChat APP when logging in, written through the setUserAccessToken method of uni-open-bridge-common
  • QQ applet user session_key, written through the setSessionKey method of uni-open-bridge-common
  • The user access_token returned by the QQ APP when logging in, written through the setUserAccessToken method of uni-open-bridge-common

If the developer needs to obtain the openid corresponding to a user, he can read the user record by himself after the user uses the corresponding login operation. The code example is as follows:

const uid = 'xx'
const appId = '__UNI_xxx'
const wxPlatform = 'mp' // mp:小程序,h5:公众号,web:web页面,app:App微信登录

const db = uniCloud.database()
const getUserRes = await db.collection('uni-id-users').doc(uid).get()

const userRecord = getUserRes.data[0]
if(!userRecord) {
  throw new Error('未匹配到此用户')
}
const wxOpenid = userRecord.wx_openid || {}
const openid = wxOpenid[wxPlatform + '_' + appId]  || wxOpenid[wxPlatform]

# Hooks

Added in uni-id-pages 1.0.8

uni-id-co is a complete cloud object, in which the registration and login processes have been fully implemented, and it is inconvenient for developers to modify it. For example, to realize the function of adding a role to a user at the time of registration, you can only modify the code of uni-id-co. So uni-id-co provides the ability to interfere with built-in logic through hooks

The uni-id hook function needs to be configured in uni-config-center. Create hooks directory under uni-config-center/uni-id and create index.js inside it with the following content

module.exports = {
  beforeRegister: function (){
    // pre-registration hook
  }
}

# beforeRegister

beforeRegister is triggered before the registered user records are stored. The hook will receive the following parameters and need to return the processed user record for storage

parameter name type description
userRecord Object The user record to be stored
clientInfo Object Client information, reference: cloud object getClientInfo

For example, adding the "teacher" role for the user registered by the application __UNI_123123, the example of the beforeRegister hook is as follows

// hook function example hooks/index.js

function beforeRegister({
  userRecord,
  clientInfo
} = {}) {
  if(clientInfo.appId === '__UNI_123123') {
    if(userRecord.role) {
      userRecord.role.push('teacher')
    } else {
      userRecord.role = ['teacher']
    }
  }
  return userRecord // 务必返回处理后的userRecord
}

module.exports = {
  beforeRegister
}

# Password Safe

By default, uni-id uses the hmac-sha1 encryption algorithm to encrypt the password. Since the uni-id-pages@1.0.28 version, the hmac-sha256 encryption algorithm has been added, and developers can choose different ones according to their needs. algorithm, it is recommended to use hmac-sha256 algorithm.

Configure in uni-config-center/uni-id/config.json, uni-id/config.json description

{
  "passwordSecret": [
    {
      "type": "hmac-sha256", // 必须指定算法类型 默认 hmac-sha1
      "version": 1
    }
  ]
}

Modify passwordSecret reference

# Upgrade hmac-256 encryption algorithm guide

For versions below uni-id-pages@1.0.28, First confirm the passwordSecret field type in uni-config-center/uni-id/config.json

The passwordSecret field may be of string or array type, examples are as follows:

// 1 string
{
  "passwordSecret": "passwordSecret-demo"
}
// 2 array
{
  "passwordSecret": [
    {
      "value": "passwordSecret-demo",
      "version": 1
    }
  ]
}

If passwordSecret is a string type, modify it to an array type, add hmac-256 algorithm to passwordSecret, and add 1 to version

{
  "passwordSecret": [
    {
      "value": "passwordSecret-demo",
      "version": 1
    },{
      "type": "hmac-256",
      "version": 2
    }
  ]
}

# Custom encryption algorithm

If the built-in encryption algorithm cannot meet business requirements, you can customize the encryption rules.

First add custom password type custom in uni-config-center/uni-id/config.json

{
  "passwordSecret": [
    {
      "value": "passwordSecret-demo",
      "version": 1
    },
    {
      "type": "hmac-sha256", // 必须指定算法类型 默认 hmac-sha1
      "version": 2
    },
    {
      "type": "custom", // 固定值 custom,代表使用自定义规则
      "version": 3
    }
  ]
}

Just create encryption and authentication methods in the uni-config-center/uni-id/custom-password.js file (if not, please create it manually).

module.exports = {
    /**
     * 密码加密
     * @param {String} password 用户输入的密码
     * @param {Object} clientInfo 客户端信息
     * @param {Object} passwordSecret config.json 匹配到的 passwordSecret
     * @return {{version, passwordHash}}
     */
    encryptPassword: function ({password, clientInfo, passwordSecret}) {
        // Must return in this format
        return {
            passwordHash: password,
            version: passwordSecret.version
        }
    },
    /**
     * 密码验证
     * @param {String} password 用户输入的密码
     * @param {Object} userRecord 用户信息
     * @param {Object} clientInfo 客户端信息
     * @param {Object} passwordSecret config.json 匹配到的 passwordSecret
     * @return {boolean}
     */
    verifyPassword: function ({password, userRecord, clientInfo, passwordSecret}) {
        return password === userRecord.password
    }
}

# Move users to uni-id

If you want to import users in your own system to uni-id, please follow the steps below

# 1. Prepare custom user password function

uni-id uses the hmac-256 password encryption algorithm by default, which may be different from your encryption algorithm, so you need to customize your password encryption function before migration. When the user logs in in uni-id for the first time, it will first use the custom verification password (verifyPassword) function to verify, so that the user can still log in with the previous password, and the user does not need to reset the password. After the user successfully logs in for the first time, the encryption algorithm rule of the user password will be upgraded to the latest algorithm rule in the configuration file.

First create a custom type of paswordSecret in the uni-config-center/uni-id/config.json file, as follows:

{
  "passwordSecret": [
    {
      "type": "custom",
      "version": 1
    }
  ]
}

Create the verifyPassword function in the uni-config-center/uni-id/custom-password.js file (if it does not exist, please create it manually) to verify the previous user password.

module.exports = {
    /**
     * 密码验证
     * @param {String} password 用户输入的密码
     * @param {Object} userRecord 用户信息
     * @param {Object} clientInfo 客户端信息
     * @param {Object} passwordSecret config.json 匹配到的 passwordSecret
     * @return {boolean}
     */
    verifyPassword: function ({password, userRecord, clientInfo, passwordSecret}) {
        return password === userRecord.password
    }
}

Notice

If the type of the latest version of passwordSecret in the configuration file is custom, then the encryption and verification of all users will use custom algorithm rules.

If it is only for migration, please add hmac-sha256 type algorithm in passwordSecret for encryption and verification of other users.

In this way, only the previous users will use custom custom rules, and other users or newly registered users after migration will use hmac-sha256 algorithm rules.

{
  "passwordSecret": [
  {
    "type": "custom",
    "version": 1
  },
  {
    "type": "hmac-sha256",
    "version": 2
  }
  ]
}

# 2. Export user data

The maximum export file size does not exceed 50MB, if it exceeds 50MB, please export multiple json files

If there is a scene where table A is associated with table B fields, it is necessary to ensure that the associated fields are consistent in A and B (special attention should be paid to various fields associated with _id)

Refer to importing data from a file

Please export the user data as a json file. Note that the json file is not a standard json file. Please follow the format below to export a user record in json format per line:

{"user_id":0,"nickname":"张三","age":25,"password":"123456"}
{"user_id":1,"nickname":"李四","age":18,"password":"000000"}

# 3. Processing user data

In uni-id, userId is the _id automatically created by the system. If you want to keep the userId of the previous user, you can map the userId to _id. If you don’t want to keep the userId, it is recommended to delete the userId field, and _id will be created in the data import .

Pay attention to the password_secret_version field, the field value needs to be changed to the version of the custom password type

Before importing to uni-id, you need to process the mapping relationship between user data and uni-id field, see the uni-id field and description below:

Field Type Default Description
_id - - Storage document ID (user ID), automatically generated by the system
ali_openid string - Alipay platform openid
apple_openid string - Apple login openid
avatar string - Avatar address (full path)
avatar_file file - Use the file type to facilitate the use of uni-file-picker components
comment string - Remarks
dcloud_appid array - list of client appids allowed to log in
department_id array - department ID
email string - email address
email_confirmed int 0 Email verification status: 0 unverified 1 verified
gender int 0 User gender: 0 unknown 1 male 2 female
invite_time timestamp - invitation time
inviter_uid array - all inviters of the user
last_login_date timestamp - Last login time
last_login_ip string - Last login IP address
mobile string - mobile phone number
mobile_confirmed int 0 mobile phone number verification status: 0 unverified 1 verified
my_invite_code string - user's own invitation code
nickname string - user nickname
password password - password, encrypted storage
password_secret_version int - passwordSecret version used for password
realname_auth object - real name authentication information; see the realname_auth structure below
register_date timestamp - registration time
register_ip string - IP address when registering
role array - user role
score int - User points, point change records can refer to: uni-id-scores table definition
status int - user status: 0 normal 1 disabled 2 reviewing 3 reviewing rejected
token array - user token
username string - username, duplicates are not allowed
wx_openid object - WeChat platform openid; see wx_openid structure below
wx_unionid string - WeChat unionid
qq_unionid string - QQ unionid
third_party object - third-party platform credentials

realname_auth structure

Field Type Default Description
auth_date timestamp - authentication passed time
auth_status int 0 authentication status: 0 unauthenticated 1 waiting for authentication 2 authentication passed 3 authentication failed
contact_email string - contact email
contact_mobile string - contact phone number
contact_person string - contact name
id_card_back string - ID card back photo URL
id_card_front string - ID card front photo URL
identity string - ID card number/business license number
in_hand string - hand-held ID photo URL
license string - Business license URL
real_name string - real name/company name
type int - User type: 0 individual user 1 enterprise user

wx_openid structure

Field Type Default Description
app string - app platform WeChat openid
mp string - WeChat MiniApp platform openid
h5 string - WeChat official account login openid
web string - PC page scan code login openid

qq_openid structure

Field Type Default Description
app string - app platform QQ openid
mp string - QQ MiniApp platform openid

# 4. Import data

In uniCloud console, find the service space where uni-id is located, select the uni-id-users table in the cloud database, click the import button, and upload users The data json file is fine.

从文件中导入数据说明

# 实名认证uni-id-pages 1.1.7+

HBuilderX 版本需大于3.7.6

实人认证相关功能建议或问题,可以加入uni-im交流群进行讨论,点此加入

基于实人认证服务实现,可以实现用户刷脸核验真实身份,完成实名认证。

目前仅APP端支持实名认证。

uni-id-pages 中内置了实名认证页面uni-id-pages/pages/userinfo/realname-verify/realname-verify

如没有实名认证需求,可以将实名认证相关页面注释:

  1. uni-id-pages/pages/userinfo/userinfo页面中,注释掉实名认证的uni-list-item标签。
  2. pages.json中注释掉实名认证页面uni_modules/uni-id-pages/pages/userinfo/realname-verify/realname-verify

# 开通与使用

  1. 使用开发者账号登录uniCloud控制台 ,选择实人认证栏目。在使用此功能前需要完成实名认证,可前往开发者中心完成实名认证。

  1. 完成实名认证后,阅读uni实名认证服务协议并点击协议下方的“同意协议并开通”按钮,便可开通实人认证服务。

  1. 实人认证为预付费业务,使用实人认证服务之前,需要先进行充值。点击页面上的“充值”按钮,并输入充值金额进行充值,充值金额最小为1元。

  1. 开通完成后,在插件市场中导入uni-id-pages至项目中。
  2. 参考配置项说明完成配置设置,详细的uni-id配置文件参考
  3. uni-config-centeruni-id-co模块上传至云端。
  4. manifest.json中找到App模块设置-打包模块设置,勾选”实人认证“。

  1. 建议在 uniCloud 中配置服务空间白名单安全配置,可以提高接口调用安全性,防止被他人盗用。可点击“添加服务空间”按钮,选择相应的服务空间完成添加服务空间白名单,服务空间添加成功后,只有列表中的服务空间才可以调用当前账号下的实人认证接口。此列表为空时,不校验调用方的服务空间。

  1. 运行iOS/Android标准基座即可测试实名认证功能。

  1. 在用户完成实名认证后,可以在uniCloud控制台查看实人认证调用记录与统计。

但此业务数据量较大,为了维持服务的稳定性,只能查看30天内的某1天的全部调用记录,默认选择当天。

系统可查看实人认证每日调用汇总数据,包括每日请求次数、每日请求成功次数、每日计费金额等汇总数据。

# 配置项说明

实名认证相关配置项如下,配置文件路径uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json,详细的uni-id配置文件参考

字段 类型 默认值 说明
idCardCertifyLimit number 1 限制每个身份证可以绑定几个账号
realNameCertifyLimit number 5 限制用户每日认证次数,防止接口被刷
sensitiveInfoEncryptSecret string 敏感信息加密密钥(长度必须32位); 见下方敏感信息加密
frvNeedAlivePhoto boolean false 是否获取认证照片

注意

# 接口参考

# 敏感信息加密

用户的姓名、身份证号、实人认证照片属于用户隐私信息,为了防止隐私信息泄露,在数据存储上使用了对称加密aes-256-cbc算法对数据进行加密。 在前端页面需要使用时,例如”获取用户实名信息“接口,只会返回脱敏后的数据,减少暴露风险,提高安全性。

由于加密密钥sensitiveInfoEncryptSecret来源于config.json配置文件,强烈建议更换为自定义的字符串,不要使用默认的密钥。 密钥长度需要是32位的字符串。

实人认证照片将会上传至云存储中,阿里云与腾讯云存储路径如下:

  • 阿里云 /{uid}.b64
  • 腾讯云 /user/id-card/{uid}.b64

注意:文件不是图片不可直接下载打开。