diff --git a/uniCloud-aliyun/cloudfunctions/uni-id-cf/index.js b/uniCloud-aliyun/cloudfunctions/uni-id-cf/index.js index 37c947f6640fbb8e531566f9e1a7d1e6735186bb..8a573dcd43cfc03ab7b1da69793230aa58959a35 100644 --- a/uniCloud-aliyun/cloudfunctions/uni-id-cf/index.js +++ b/uniCloud-aliyun/cloudfunctions/uni-id-cf/index.js @@ -7,58 +7,51 @@ const uniIdConfig = createConfig({ })._config const db = uniCloud.database() const dbCmd = db.command -exports.main = async (event, context) => { - /** - * UNI_WYQ:这里的uniID换成新的,保证多人访问不会冲突 - */ - uniID = uniID.createInstance({ - context - }) - //event为客户端上传的参数 - console.log('event : ' + JSON.stringify(event)) - let params = event.params || {} - - //防止黑客恶意破解登录,连续登录失败一定次数后,需要用户提供验证码 - const getNeedCaptcha = async () => { - //当用户最近“2小时内(recordDate)”登录失败达到2次(recordSize)时。要求用户提交验证码 - const now = Date.now(), - recordDate = 120 * 60 * 1000, - recordSize = 2; - const uniIdLogCollection = db.collection('uni-id-log') - let recentRecord = await uniIdLogCollection.where({ - deviceId: params.deviceId || context.DEVICEID, - create_date: dbCmd.gt(now - recordDate), - type: 'login' - }) - .orderBy('create_date', 'desc') - .limit(recordSize) - .get(); - return recentRecord.data.filter(item => item.state === 0).length === recordSize; - } - - //设置某些模块不需要token(也就是登录成功后)才能操作,如果需要token就获取当前操作账户的uid - let noCheckAction = [ - 'register', 'checkToken', 'login', 'logout', 'sendSmsCode', - 'createCaptcha', 'verifyCaptcha', 'refreshCaptcha', 'inviteLogin', - 'login_by_weixin', 'login_by_univerify', 'login_by_apple', 'loginBySms', 'resetPwdBySmsCode' - ] - let payload; - console.log(event.action); - if (!noCheckAction.includes(event.action)) { - if (!event.uniIdToken) { +exports.main = async (event, context) => { + //UNI_WYQ:这里的uniID换成新的,保证多人访问不会冲突 + uniID = uniID.createInstance({context}) + console.log('event : ' + JSON.stringify(event)) + /* + 1.event为客户端 uniCloud.callFunction填写的data的值,这里介绍一下其中的属性 + action:表示要执行的任务名称、比如:登陆login、退出登陆 logout等 + params:业务数据内容 + uniIdToken:系统自动传递的token,数据来源客户端的 uni.getStorageSync('uni_id_token') + */ + const {action,uniIdToken,params} = event; + let params = event.params || {}; + /* + 2.在某些操作之前我们要对用户对身份进行校验(也就是要检查用户的token)再将得到的uid写入params.uid + 校验用到的方法是uniID.checkToken 详情:https://uniapp.dcloud.io/uniCloud/uni-id?id=checktoken + + 讨论,我们假设一个这样的场景,代码如下。 + 如: + uniCloud.callFunction({ + name:"xxx", + data:{ + "params":{ + uid:"通过某种方式获取来的别人的uid" + } + } + }) + 用户就这样轻易地伪造了他人的uid传递给服务端,有一句话叫:前端从来的数据是不可信任的 + 所以这里我们需要将uniID.checkToken返回的uid写入到params.uid + */ + let noCheckAction = ['register','checkToken','login','logout','sendSmsCode','createCaptcha','verifyCaptcha','refreshCaptcha','inviteLogin','login_by_weixin','login_by_univerify','login_by_apple','loginBySms','resetPwdBySmsCode'] + if (!noCheckAction.includes(action)) { + if (!uniIdToken) { return { code: 403, msg: '缺少token' } } - payload = await uniID.checkToken(event.uniIdToken) + let payload = await uniID.checkToken(uniIdToken) if (payload.code && payload.code > 0) { return payload } params.uid = payload.uid } - //注册成功后为用户执行相关操作,如创建该用户的积分表等 + //3.注册成功后创建新用户的积分表方法 async function registerSuccess(uid) { await db.collection('uni-id-scores').add({ user_id: uid, @@ -69,7 +62,7 @@ exports.main = async (event, context) => { create_date: Date.now() }) } - //记录成功登录的日志 + //4.记录成功登录的日志方法 const loginLog = async (res = {}, type = 'login') => { const now = Date.now() const uniIdLogCollection = db.collection('uni-id-log') @@ -94,10 +87,8 @@ exports.main = async (event, context) => { return await uniIdLogCollection.add(logData) } - - - let res = {} - switch (event.action) { + let res = {} + switch (action) { //根据action的值执行对应的操作 case 'bind_mobile_by_univerify': let { appid, apiKey, apiSecret @@ -132,7 +123,7 @@ exports.main = async (event, context) => { console.log(res); break; case 'register': - let { + var { username, password, nickname } = params if (/^1\d{10}$/.test(username)) { @@ -156,12 +147,33 @@ exports.main = async (event, context) => { await registerSuccess(res.uid) } break; - case 'login': + case 'login': + //防止黑客恶意破解登录,连续登录失败一定次数后,需要用户提供验证码 + const getNeedCaptcha = async () => { + //当用户最近“2小时内(recordDate)”登录失败达到2次(recordSize)时。要求用户提交验证码 + const now = Date.now(), + recordDate = 120 * 60 * 1000, + recordSize = 2; + const uniIdLogCollection = db.collection('uni-id-log') + let recentRecord = await uniIdLogCollection.where({ + deviceId: params.deviceId || context.DEVICEID, + create_date: dbCmd.gt(now - recordDate), + type: 'login' + }) + .orderBy('create_date', 'desc') + .limit(recordSize) + .get(); + return recentRecord.data.filter(item => item.state === 0).length === recordSize; + } + let passed = false; let needCaptcha = await getNeedCaptcha(); - console.log('needCaptcha',needCaptcha); + console.log('needCaptcha', needCaptcha); if (needCaptcha) { - res = await uniCaptcha.verify({...params,scene:'login'}) + res = await uniCaptcha.verify({ + ...params, + scene: 'login' + }) if (res.code === 0) passed = true; } @@ -194,16 +206,16 @@ exports.main = async (event, context) => { await loginLog(res) break; case 'checkToken': - res = await uniID.checkToken(event.uniIdToken); + res = await uniID.checkToken(uniIdToken); break; case 'logout': - res = await uniID.logout(event.uniIdToken) + res = await uniID.logout(uniIdToken) break; case 'sendSmsCode': // 测试期间短信统一用 123456 正式项目删除即可 return uniID.setVerifyCode({ mobile: params.mobile, - code:'123456', + code: '123456', type: params.type }) // 简单限制一下客户端调用频率 @@ -310,21 +322,27 @@ exports.main = async (event, context) => { break; case 'refreshCaptcha': res = await uniCaptcha.refresh(params) - break; - case 'registerAdmin': - let {username,password} = params - let {total} = await db.collection('uni-id-users').where({role: 'admin'}).count() - if (total) { - return { - code: 10001, - message: '超级管理员已存在,请登录...' - } - } - return this.ctx.uniID.register({ - username, - password, - role: ["admin"] - }) + break; + case 'registerAdmin': + var { + username, password + } = params + let { + total + } = await db.collection('uni-id-users').where({ + role: 'admin' + }).count() + if (total) { + return { + code: 10001, + message: '超级管理员已存在,请登录...' + } + } + return this.ctx.uniID.register({ + username, + password, + role: ["admin"] + }) break; default: res = { @@ -335,4 +353,4 @@ exports.main = async (event, context) => { } //返回数据给客户端 return res -}; +};