提交 07dc7049 编写于 作者: DCloud_JSON's avatar DCloud_JSON

新增uni-id-cf云函数的代码注释,重点解释token的验证方式和原因。

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