# uni cloud integrated security network

HBuilderX 3.6.8+ support

# Introduction

The problems with network security are many:

  1. The client is trusted. Due to the statelessness of http, the authenticity of the client is difficult to guarantee. Simulating the client and re-signing the apk are hard to guard against.
  2. The network is trusted. Even HTTPS requests will be captured, and routers and local operators may obtain your data, hijack and rewrite your requests.

When the attacker knows what kind of data your server receives, he can impersonate the client and submit fake data to attack your server.

Especially when your business involves promotions, rebates, incentive videos and other scenarios, it is very easy to be swiped. Sweeping wool is already a very mature gray industry, where there are loopholes, there are opportunities for them to make money.

DCloud provides developers with both the client engine uni-app and the cloud engine uniCloud, which are now further upgraded to provide cloud-integrated security network capabilities.

When uni-app connects to uniCloud, you can choose whether to enable the secure network. Through a high-security protection mechanism, it solves the problem of client trust and network trust, and prevents client forgery and communication content capture.

The uni cloud integrated security network provides the following two practical functions:

Function name Function description Whether encoding is required Specific documents
Client verification Specify a legal client, including package name, certificate, and appid. Untrusted clients will not be able to request the server Only configuration, no coding required Documentation
Network transmission data encryption Encrypt the network transmission data end-to-end to prevent interception and tampering by intermediate nodes Need to set the encryption parameter in the code of the network request Documentation

Platform Difference Description

App WeChat MiniApp Web Other MiniApp
3.6.8+ 3.6.8+ x x

注意:安全网络只支持微信小程序和App。并且App的安全级别更高。安全网络仅在uni-app客户端连unicloud云函数/云对象生效,云函数url化场景下会直接跳过安全校验。

# How to activate

No matter which function of the security network is used, the security network must be activated first. Apps and WeChat MiniApp are slightly different, but they generally go through the following process:

  1. Front-end application configuration: Specify the application to be activated in the application management of https://dev.dcloud.net.cn/, and in the "Information of each platform "Configure the app's package name, signature digest or appid of the WeChat applet.
  2. Cloud configuration: Select a service space in uniCloud console, and associate an application configured in dev on the "Safe Network" page.

The details of the App and WeChat platforms are as follows:

# Open security network on App platform

  1. In the Developer Center Application Details --> Certificate Management, fill in the package name and signature of the Android application and the bundleId of the iOS application. An application can only have one distribution certificate configuration, but can have multiple development certificate configurations

证书管理

  1. In the uniCloud console, associate the application that allows sending secure network requests

关联应用到服务空间安全网络

In essence, the security network is bound to the application's appid, package name, certificate and other information. It's just that these information are uniformly configured in dev and selected in the web console of uniCloud. Therefore, be sure to pay attention to whether the official version of the dev configuration and the package name and signature of the test version are correct.

  1. Enable the security network module for the app platform in the manifest.json file in the project root directory

App云端一体安全网络模块

Note: It will take effect after packaging. Custom Playground needs to be packaged for testing.

  1. Create a data table opendb-app-client-key in the service space for saving and issuing to customers end key pair.
  • If you are in uniCloud console, the new table interface is in other categories of opendb tables
  • If you right-click on the database directory of HBuilderX and create a new one, you can directly search for opendb-app-client-key. Remember to upload it to the uniCloud service space after creating it.

Reference document: Create a table

  • Do not delete or modify the content of this collection, otherwise some clients will not be able to send secure network requests (the client can only be used normally after reinstalling the client or clearing the client data)
  • If redis is enabled in the service space, a client key pair will be automatically stored in redis to speed up the processing of secure network requests. The key used is unicloud:secure:app-client-key:{appId}:{deviceId}:string
  • It is strongly recommended to enable the redis function and associate the redis extension in the cloud function package.json, will greatly speed up the access speed and reduce the number of database requests. Because the encryption behavior of the secure network has taken more time than the ordinary network, so commercial projects must enable redis to ensure the speed. In the uniCloud console, click redis to activate.
  1. Upload any schema file to the service space to trigger an update of the clientDB cloud module

legacy

  • Safety Network does not yet support offline packaging, and will provide an offline packaging solution in the future

# Wechat MiniApp opens a safe network

The implementation of the secure network on the WeChat MiniApp relies on some user-level credentials provided by WeChat. So you need to download uni-id-pages and uni-open-bridge, and in the app Initialize in .vue.

** Whether it is processing encrypted requests or requiring authentication, the cloud function of the client must rely on uni-id-common and uni-open-bridge-common when processing requests initiated by WeChat MiniApp**

  1. Fill in the appId of the WeChat MiniApp in Developer CenterApplication Details--> [Name to be determined]. An application can have only one release configuration, but can have multiple development configurations

微信小程序AppId绑定

  1. In the uniCloud console, associate the application that allows sending secure network requests

关联应用到服务空间安全网络

  1. Import uni-id-pages into the project

The uni-id-pages plugin is a cloud-integrated login plugin. In fact, the security network only needs the uni-id-co cloud object. Whether to use the front-end login page in the plug-in is determined by the developer himself according to the business.

  1. Import the uni-open-bridge plug-in into the project

The security network relies on WeChat's access_token, session_key, encrypt_key and other credentials on the WeChat MiniApp. These credentials need to be taken over by uni-open-bridge.

  1. Configure uni-id and uni-open-bridge

Log in to the WeChat public platform https://mp.weixin.qq.com/,obtain the fixed MiniAppappid and secret of the WeChat applet, and configure them in uni-id-config

// uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json
{
  "dcloudAppid": "__UNI__xxxxxx", // 在项目的 manifest.json 中
  "mp-weixin": {
    "tokenExpiresIn": 259200,
    "oauth": {
      "weixin": {
        "appid": "", // 微信公众平台申请的小程序 appid
        "appsecret": "" // 微信公众平台申请的小程序 secret
      }
    }
  }
}

Configure uni-open-bridge timing task, regularly get access_token from WeChat server and save it to Redis or database

// uniCloud/cloudfunctions/common/uni-config-center/uni-open-bridge/config.json
{
  "schedule": {
    "__UNI__xxxxxx": { // dcloudAppid, 需要和 `uni-config-center` uni-id中的配置一致
      "enable": true, // 任务全局开关,优先级最高
      "weixin-mp": { // 平台,目前仅支持 微信小程序、微信 H5,详情参见 https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#platform
        "enable": true, // 当前平台任务开关
        "tasks": ["accessToken"] // 要执行的任务,微信小程序支持 accessToken
      }
    }
  },
  "ipWhiteList": ["0.0.0.0"] // 用于 URL化后 http 调用的服务器IP白名单,即指定ip的服务器才可以访问URL化后的`uni-open-bridge云对象
}

Note: When copying the content of this file, you need to remove the comment. Standard json does not support comments. In HBuilderX, multiple selection // can be used to remove comments in batches.

If the project has used uni-id-pages and uni-open-bridge before, the above steps can be omitted.

  1. 在应用的生命周期 onLaunch(能保证在调用安全网络请求前调用完成的时机均可) 调用 uniCloud.initSecureNetworkByWeixin(),进行安全网络请求前的握手操作,关于此接口详细描述见:uniCloud.initSecureNetworkByWeixin

对于使用uni-id-pages的项目App.vue页面需要补充如下代码,不使用uni-id-pages的开发者需要按照此文档进行操作:不使用uni-id-pages时如何使用微信小程序安全网络

<script>
  export default {
    onLaunch: async function() {
      // #ifdef MP-WEIXIN
      const userInfo = uniCloud.getCurrentUserInfo()
      const callLoginByWeixin = userInfo.tokenExpired < Date.now() // 用户为未登录状态时调用一次微信登录
      await uniCloud.initSecureNetworkByWeixin({
        callLoginByWeixin: callLoginByWeixin
      })
      // #endif
    }
  }
</script>

Note: This method will call the login of the WeChat MiniApp once internally, and then use the returned code to call the secureNetworkHandshakeByWeixin method of uni-id-co (newly added in uni-id-pages 1.0.27)

  1. In the manifest.json file in the root directory of the project, enable the cloud integrated security network module for the WeChat MiniApp platform

微信小程序云端一体安全网络模块

# 不使用uni-id-pages时如何使用微信小程序安全网络

新增于HBuilderX 3.7.7

对于部分已有用户体系,不希望引入uni-id-pages的开发者,可使用如下方案来使用微信小程序安全网络。

客户端需调整为在调用安全网络请求前使用uniCloud.initSecureNetworkByWeixin方法传入用户openid

// app.js
<script>
  export default {
    onLaunch: async function() {
      // #ifdef MP-WEIXIN
      // 调用自有服务、云函数进行微信登录或以其他方式获取openid
      const openid = 'xxx'
      await uniCloud.initSecureNetworkByWeixin({
        openid: openid
      })
      // #endif
    }
  }
</script>

云函数内需要调用uni-open-bridge-common将微信应用级access_token及登录用户的session_key同步到uniCloud数据库,以便安全网络云端能从微信获取解密用参数。

uni-open-bridge-common使用注意事项

uni-open-bridge-common仍依赖uni-id的配置获取微信小程序appid,如何配置请参考:uni-id config

如果从自有服务器同步access_token和session_key到uniCloud数据库内可以使用uni-open-bridge提供的url化调用方式,请参考:uni-open-bridge url化调用

如果从云函数内同步access_token和session_key给安全网络按如下文档进行

云函数存储微信小程序应用级access_token

开发者应在自己云函数获取access_token,传递给uni-open-bridge-common进行存储,以供安全网络使用。或使用uni-open-bridge云函数的定时任务自动获取access_token,参考:应用级access_token

微信access_token有一些特性,处理不好容易出现bug,请务必详读微信公众平台关于access_token的说明(微信小程序、公众号逻辑一样):微信公众平台access_token

await require('uni-open-bridge-common').setAccessToken({
  dcloudAppid: '__UNI__xxx',
  platform: 'weixin-mp'
}, {
  access_token: accessToken
}, 7200) // 新获取的accessToken有效期是2小时

云函数存储微信用户session_key

开发者应在用户调用微信登录使将openid、session_key传递给uni-open-bridge-common进行存储,以供安全网络使用

await require('uni-open-bridge-common').setSessionKey({
  dcloudAppid: '__UNI__xxx',
  openid,
  platform: 'weixin-mp'
}, {
  session_key: sessionKey
}, 30 * 24 * 60 * 60) // session_key并没有固定有效期,暂以30天进行存储

# Client mandatory verification

Added in HBuilderX 3.6.8

Client authentication is used to ensure the authenticity of the client that initiates the request, and only the specified client can access the cloud function.

The entire process of the client verification function is controlled by uniCloud. After this function is enabled, the client without access will be directly refused to call the cloud function.

The developer first selects which client applications can establish a secure network with uniCloud on the secure network page of uniCloud console, and then enables the mandatory client verification on the page separately .

Remember

  1. Since the uni security network does not support the web, once the client-side mandatory verification is enabled, the web side will not be able to connect to the cloud function.
  2. 由于uni安全网络必须绑定自己的应用,所以不支持标准基座的真机运行,只能使用自定义基座。
  3. 如果存在旧客户端,但是想在新版本使用安全网络,建议不开启客户端校验,使用请求加密来实现安全通讯。通过判断版本号,旧版本不强制要求使用加密。在旧版本量很小的时候去除这个逻辑。

After the client authentication function is enabled, security authentication is enabled for all cloud functions by default, and only applications configured in the list of secure network applications are allowed to access cloud functions. But sometimes, there is a need to exclude a certain cloud function. For example, if the specified cloud function verifies or does not verify the client identity, this cloud function may require url for external access.

Therefore, uni security network provides custom client verification rules.

# Custom client validation rules

On the Security Network page of the uniCloud web console, you can turn on the custom rule switch. After the custom rules are enabled, the unified client verification of all cloud functions will no longer be performed. Instead, cloud functions that are not matched by the rule do not perform client authentication.

The following example is a simple custom rule configuration:

{
  "verify-client": [{ // 可访问云函数verify-client的应用列表
    "appId": "__UNI_xxxx",  // 客户端的DCloud AppId
    "platform": "android",  // 客户端平台,有三个可选值:android(安卓)、ios(iOS)、mp-weixin(微信小程序)。注意是小写
    "version": "production" // 客户端版本,有两个可选值:production(正式版)、development(测试版)。注意是小写
  }]
}

The above rules mean that the cloud function named verify-client can only be accessed by the application whose appid is __UNI_xxxx, the platform is the client platform is android, and is the official version; other clients cannot access it. This cloud function; and except verify-client, other cloud functions can be accessed by any client at will.

If you want to add more rules, add more arrays in json, each array is a rule. For example, if you want to configure the ios platform, add an array.

Note: The custom rule is a standard json and does not support writing comments. If you want to copy the sample code, please be sure to remove the comments.

The cloud function name is the key of json, but multiple cloud functions can be written. Including the following ways of writing:

  1. Single cloud function verify-client
  2. Multiple cloud functions verify-client1, verify-client2, note that commas are English commas
  3. The wildcard * represents all cloud functions

When matching the custom rule configuration of a cloud function, the configuration of a single cloud function name is used first, followed by the configuration of multiple cloud function names, and finally the configuration of wildcards. If there is no match, the logic of verifying the client will not be executed for this cloud function.

Notice

  • 如果修改客户端验证配置需要重新打包做出修改的客户端,如果是正在运行期间修改了配置需要重新运行客户端才会生效。这部分配置会同步到客户端,比如你添加了某个函数作为必须验证才使用的函数,这时候客户端需要新的配置才会在请求新函数是带上客户端验证参数,因此需要重新打包。
  • To perform client-side verification on clientDB requests, use uni-clientDB as the cloud function name

# Data encryption transmission

In addition to verifying the identity of the client, the uni security network also provides encryption of data transmitted up and down the network.

At this time, it is necessary to write codes on both the client and the server. It is not necessary to write a specific encryption and decryption algorithm. Instead, it is necessary to specify which requests and which data to encrypt on the client, and to verify whether the client is specified correctly in the cloud. conditions of.

Encryption and decryption use the internationally accepted high-bit AES algorithm.

The specific writing method is as follows:

# Client request cloud function

When the client calls the cloud function through callFunction, add the secretType parameter.

uniCloud.callFunction({
  name: 'collection',
  data: {
    name: 'user'
  },
  secretType: 'both' //both指上下行数据都加密,具体见下面的secretType章节
}).then(res => {
  const {
    errCode,
    errMsg
  } = res.result
  if(errCode) {
    uni.showModal({
      content: errMsg,
      showCancel: false
    })
  }
})

That is, each callFunction request can specify whether to encrypt, and whether to encrypt uplink data or downlink data.

Notice

  • Security network related interfaces do not support local debugging. Even if the connection to local cloud functions is checked in HBuilderX, the client will automatically connect to cloud cloud functions when requesting.
  • Since the cloud vendor will handle the errors thrown by the cloud function, in order to ensure that the client gets the correct error code, the cloud function will include the specific error in res.result in the success callback when returning a security network error
  • Different from the handshake behavior of the service space security network module and the cloud function request, if an error is encountered, it will be thrown directly. If the App side fails to request the cloud to issue the public key, enter the fail callback of callFunction

# The client requests the cloud object

When the client calls the cloud object through importObject, configure whether to encrypt each method call through the secretMethods parameter.

const obj = uniCloud.importObject('object-name', {
  secretMethods: {'login':'both'} // 对login方法设置为上下行的数据均要加密。也支持配置所有方法设置加密,参见下面的 secretMethods 说明
})
obj.test().then(()=>{}).catch(err => {
  uni.showModal({
    content: err.errMsg || err.message,
    showCancel: false
  })
})

That is, when a cloud object is imported, configure whether the request for a certain method should be encrypted, and whether to encrypt uplink data or downlink data. Then when the client calls the corresponding method of the cloud object, it will automatically execute according to this configuration.

# clientDB

clientDB does not currently support encrypted network data transmission. However, client authentication can still be used.

# Parameter Description

secretType attribute description

value description
none The uplink and downlink are not encrypted, the default value
request Only encrypt the upstream data when the client requests, and the data sent by the server is not encrypted
response The client does not encrypt data when requesting, only encrypts the data delivered by the server
both Both client and server uplink and downlink data are encrypted
  • The reason why such fine encryption configuration is provided is that encryption and decryption consume resources and increase waiting time. Generally, only the confidential data that really needs to be protected from network theft is encrypted.

secretMethods attribute description

secretMethods is the method name in the cloud object that needs to be encrypted.

  • Set encryption for all methods, e.g. secretMethods: {'*':'both'}
  • Configure encryption for each method, for example secretMethods: {'login':'both'}, specify secretType of login method as both

Method-level configuration has the highest priority, for example secretMethods: {'*':'response', 'login':'both'}, login's both override '*':'response'

Notice

  • The security network of the WeChat MiniApp depends on the login logic, so when the client detects that a security network request is sent, if the user is not logged in, it will automatically call the loginByWeixin interface of uni-id-co

# Service-Terminal

The uni cloud integrated security network has encapsulated complex security-related algorithms at the bottom layer. Developers only need to care about which requests and which data are encrypted.

**Whether the client receives cloud data or the cloud receives client data, the data obtained by the developer's code will always be decrypted data. **

But there is a caveat in the cloud: In order to prevent the client from forging the secretType to obtain sensitive data from the server, the server should prevail. If the secretType carried by the client does not meet the requirements, the response data should be rejected.

The sample code is as follows:

# Verify secretType in cloud function

There is a secretType in the context of the cloud function. If the returned data of this cloud function must be encrypted, the following method should be used to verify whether the client's request is legal.

exports.main = async (event, context) => {
  const secretType = context.secretType
  // secretType is the parameter secretType passed by the client to call uniCloud.callFunction

  if (secretType !== 'both' || secretType !== 'response') {
    throw new Error('secretType invalid') // 拒绝返回有效数据
  }
}

# Verify secretType in cloud object

There is secretType in this of the cloud object. If the return data of the reward method of this cloud object must be encrypted, the following method should be used to verify whether the client's request is legal.

module.exports = {
  async _before() {
    const methodName = this.getMethodName()
    const clientInfo = this.getClientInfo()
    const secretType = clientInfo.secretType
    // methodName is the method name called by the client
    // secretType is the parameter passed by the client calling uniCloud.importObject secretMethods

    if (methodName === 'reward' && (secretType !== 'both' || secretType !== 'response')) {
      throw new Error('secretType invalid') // 拒绝返回有效数据
    }
  }
}

# Error code

Since HBuilderX 3.6.9, the safety network uses the following error specifications. It is not recommended to use the error codes before. Error specification reference for use with secure networks: Error Specification

# Client errors

Error code Error details
10001 App platform does not support MiniApp sdk and standard dock
10003 App platform appKey is empty, please try to repackage
10009 App platform encryption failed
10010 App platform decryption failed
20101 The client information is not in the client information list that is allowed to be accessed. If the cloud adjustment configuration needs to repackage/run the client to take effect
20102 The WeChat MiniApp platform failed to obtain the encryption key

# Cloud errors

Error code Error details
50000 System Error
60101 Client AppId is missing
60102 Client DeviceId is missing
60103 Client OsName is missing
60200 The security network is not activated in the service space
60201 The AppId of the current application has not been associated with the uniCloud security network
60202 The current application AppId has been associated with the uniCloud security network, but the current client platform is not associated
70001 Client time error
70002 The AppId of the client fails to pass the verification
70003 The client DeviceId has not passed the verification
70004 The client information has not passed the verification
70005 User account does not exist
70006 User openid not found
70007 Failed to obtain encryption key
70008 The signature required for client authentication is missing, see the detailed description below
70009 Encryption key not found
70010 Access forbidden by emulator or rooted device

微信小程序加解密时还会使用uni-id-common的checkToken方法,相关错误码参考:uni-id错误码

# 70008 Error detailed description

If an unexpected 70008 error occurs, please follow the steps below to troubleshoot

  1. Check whether the security network module is enabled in the project manifest.json
  2. After modifying the verification configuration of the cloud client, it needs to be recompiled and run. For example: a cloud function that needs to verify the client has not been configured before, and the client needs to be recompiled after the cloud function is configured to require the client to be verified

# Tips

  1. Security is relative, there is no absolute security. The uni cloud integrated security network only helps ordinary developers achieve the industry's first-class security level.
  2. Security involves a wide range. In addition to the scope covered by the secure network, there are also account passwords, various keys and secrets in the cloud, which must be well protected. Many security incidents are caused by programmers mistakenly submitting key keys to code hosting platforms such as github.
  3. Security comes at a price. The larger the encrypted data, the longer it will take to encrypt and decrypt.
  4. 开启安全网络后,如果觉的联网速度变慢,一方面要开启redis,并在云函数中挂载redis扩展库;另一方面控制加密的数据量,没必要加密的数据就别加密。