diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js index 1a05d9a0d7d10ce47957c30da96ac66ffebf3cd8..f5888c42247739b60ef3be81774e445d5536db06 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js @@ -6,6 +6,8 @@ const verifyCollectionName = 'opendb-verify-codes' const verifyCollection = db.collection(verifyCollectionName) const deviceCollectionName = 'uni-id-device' const deviceCollection = db.collection(deviceCollectionName) +const openDataCollectionName = 'opendb-open-data' +const openDataCollection = db.collection(openDataCollectionName) const USER_IDENTIFIER = { username: 'username', @@ -78,6 +80,7 @@ module.exports = { userCollection, verifyCollection, deviceCollection, + openDataCollection, USER_IDENTIFIER, USER_STATUS, CAPTCHA_SCENE, diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js index 24cbbc7b4d78dbf5ffcbe1cc3a92ef8e01da4e75..840fea8a5399342ccd7d5f36020ad6c8770c98b5 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js @@ -63,7 +63,8 @@ const { } = require('./module/verify/index') const { refreshToken, - setPushCid + setPushCid, + secureNetworkHandshakeByWeixin } = require('./module/utils/index') const { getInvitedUser, @@ -576,5 +577,9 @@ module.exports = { * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-apple * @returns */ - unbindApple + unbindApple, + /** + * 安全网络握手,目前仅处理微信小程序安全网络握手 + */ + secureNetworkHandshakeByWeixin } diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/utils.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..7d3e0f3668115023247947f26e46a89a65fba31a --- /dev/null +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/utils.js @@ -0,0 +1,18 @@ +let redisEnable = null +function getRedisEnable() { + // 未用到的时候不调用redis接口,节省一些连接数 + if (redisEnable !== null) { + return redisEnable + } + try { + uniCloud.redis() + redisEnable = true + } catch (error) { + redisEnable = false + } + return redisEnable +} + +module.exports = { + getRedisEnable +} \ No newline at end of file diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js index 2a0f609d2f48346d7dde5558a40b460933f17b74..a01435d98030807fb315e8d31feb5f12d1a4c484 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js @@ -5,8 +5,14 @@ const { const { ERROR } = require('../../common/error') +const { + getRedisEnable +} = require('./utils') +const { + openDataCollection +} = require('../../common/constants') -function decryptWeixinData ({ +function decryptWeixinData({ encryptedData, sessionKey, iv @@ -31,7 +37,7 @@ function decryptWeixinData ({ return decoded } -function getWeixinPlatform () { +function getWeixinPlatform() { const platform = this.clientPlatform const userAgent = this.getClientInfo().userAgent switch (platform) { @@ -48,7 +54,7 @@ function getWeixinPlatform () { } } -async function saveWeixinUserKey ({ +async function saveWeixinUserKey({ openid, sessionKey, // 微信小程序用户sessionKey accessToken, // App端微信用户accessToken @@ -85,7 +91,36 @@ async function saveWeixinUserKey ({ } } -function generateWeixinCache ({ +async function saveSecureNetworkCache({ + code, + openid, + unionid, + sessionKey +}) { + const { + appId + } = this.getClientInfo() + const key = `uni-id:${appId}:weixin-mp:code:${code}:secure-network-cache` + const value = JSON.stringify({ + openid, + unionid, + session_key: sessionKey + }) + // 此处存储的是code的缓存,有效期两天即可 + const expiredSeconds = 2 * 24 * 60 * 60 + + await openDataCollection.doc(key).set({ + value, + expired: Date.now() + expiredSeconds * 1000 + }) + const isRedisEnable = getRedisEnable() + if (isRedisEnable) { + const redis = uniCloud.redis() + await redis.set(key, value, 'EX', expiredSeconds) + } +} + +function generateWeixinCache({ sessionKey, // 微信小程序用户sessionKey accessToken, // App端微信用户accessToken refreshToken, // App端微信用户refreshToken @@ -118,7 +153,7 @@ function generateWeixinCache ({ } } -function getWeixinOpenid ({ +function getWeixinOpenid({ userRecord } = {}) { const weixinPlatform = getWeixinPlatform.call(this) @@ -130,7 +165,7 @@ function getWeixinOpenid ({ return wxOpenidObj[`${weixinPlatform}_${appId}`] || wxOpenidObj[weixinPlatform] } -async function getWeixinCacheFallback ({ +async function getWeixinCacheFallback({ userRecord, key } = {}) { @@ -143,7 +178,7 @@ async function getWeixinCacheFallback ({ return weixinCache && weixinCache[key] } -async function getWeixinCache ({ +async function getWeixinCache({ uid, userRecord, key @@ -177,7 +212,7 @@ async function getWeixinCache ({ }) } -async function getWeixinAccessToken () { +async function getWeixinAccessToken() { const weixinPlatform = getWeixinPlatform.call(this) const appId = this.getClientInfo().appId @@ -194,5 +229,6 @@ module.exports = { generateWeixinCache, getWeixinCache, saveWeixinUserKey, - getWeixinAccessToken + getWeixinAccessToken, + saveSecureNetworkCache } diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin-mobile.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin-mobile.js index 2b219483e89ce10fbd38d57306aabf766c77f3b0..c27c2b21a4489e2463c6a6ea24c954e5b619afe9 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin-mobile.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin-mobile.js @@ -2,10 +2,7 @@ const { initWeixin } = require('../../lib/third-party/index') const { - getWeixinPlatform, - getWeixinAccessToken, - generateWeixinCache, - saveWeixinUserKey + getWeixinAccessToken } = require('../../lib/utils/weixin') const { ERROR diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js index 84c7ddc1f254894ea224ca2d3cc1e401b0135052..21d60718300353fafd043f17a10de8055f5b9a8b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js @@ -11,7 +11,8 @@ const { const { generateWeixinCache, getWeixinPlatform, - saveWeixinUserKey + saveWeixinUserKey, + saveSecureNetworkCache } = require('../../lib/utils/weixin') const { LOG_TYPE @@ -37,7 +38,9 @@ module.exports = async function (params = {}) { this.middleware.validate(params, schema) const { code, - inviteCode + inviteCode, + // 内部参数,暂不暴露 + secureNetworkCache = false } = params const { appId @@ -81,6 +84,18 @@ module.exports = async function (params = {}) { expired: accessTokenExpired // App端微信用户accessToken过期时间 } = getWeixinAccountResult + if (secureNetworkCache) { + if (weixinPlatform !== 'mp') { + throw new Error('Unsupported weixin platform, expect mp-weixin') + } + await saveSecureNetworkCache({ + code, + openid, + unionid, + sessionKey + }) + } + const { type, user diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js index 11729f6b943df4fcac6c01fd32397fb7a33b4f79..0ec67a57687aef5db7c35ccdce61f4027eeb4db8 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js @@ -1,4 +1,5 @@ module.exports = { refreshToken: require('./refresh-token'), - setPushCid: require('./set-push-cid') + setPushCid: require('./set-push-cid'), + secureNetworkHandshakeByWeixin: require('./secure-network-handshake-by-weixin') } diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/secure-network-handshake-by-weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/secure-network-handshake-by-weixin.js new file mode 100644 index 0000000000000000000000000000000000000000..82ea0b3762cd6459309ad794b87058feb16b2b71 --- /dev/null +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/secure-network-handshake-by-weixin.js @@ -0,0 +1,73 @@ +const { + ERROR +} = require('../../common/error') +const { + initWeixin +} = require('../../lib/third-party/index') +const { + saveWeixinUserKey, + saveSecureNetworkCache +} = require('../../lib/utils/weixin') +const loginByWeixin = require('../login/login-by-weixin') +/** + * 微信安全网络握手 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#set-push-cid + * @param {object} params + * @param {string} params.code 微信登录返回的code + * @param {boolean} params.callLoginByWeixin 是否同时调用一次微信登录 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + code: 'string', + callLoginByWeixin: { + type: 'boolean', + required: false + } + } + this.middleware.validate(params, schema) + let platform = this.clientPlatform + if (platform !== 'mp-weixin') { + throw new Error(`[secureNetworkHandshake] platform ${platform} is not supported`) + } + const { + code, + callLoginByWeixin = false + } = params + if (callLoginByWeixin) { + return loginByWeixin.call(this, { + code, + secureNetworkCache: true + }) + } + + const weixinApi = initWeixin.call(this) + let getWeixinAccountResult + try { + getWeixinAccountResult = await weixinApi.code2Session(code) + } catch (error) { + console.error(error) + throw { + errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED + } + } + const { + openid, + unionid, + sessionKey // 微信小程序用户sessionKey + } = getWeixinAccountResult + await saveSecureNetworkCache.call(this, { + code, + openid, + unionid, + sessionKey + }) + await saveWeixinUserKey.call(this, { + openid, + sessionKey + }) + + return { + errCode: 0 + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json index d09b7e62c6e2a76f61c1a839cb7bd68f8d0c5d09..e4890868df6b9c17f2d498014d0a8d12947d41f4 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json @@ -14,6 +14,10 @@ "uni-open-bridge-common": "file:../../../../uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common" }, "extensions": { - "uni-cloud-sms": {} + "uni-cloud-sms": {}, + "uni-cloud-redis": {} + }, + "cloudfunction-config": { + "keepRunningAfterReturn": false } }