个人案例
- 百熟优质果
全程使用云开发写的电商系统,内容包含了首页、购物车、订单列表、后台管理端(发货、导出订单、查询订单)等等
使用小程序云开发写的电商系统扫码体验
- 征文大学篇 - 云开发·后端鉴权思路分享
[图片] 使用场景介绍 微信小程序的进入形式决定了它更适合充当一种“工具”的角色,适合在用户想起它、要用它的时候主动启动。基于此想法,中大猫谱小程序主要服务于猫猫信息记录、搜索的功能,旨在帮助改善校园流浪猫的生存状况、帮助大众了解猫猫及救助知识,同时帮助动保组织管理猫猫资料、募集救助(绝育、治疗)流浪猫所需的资金,为生态环境保护献一份力。 (— 广告时间结束 —) 如我们所知,微信小程序对于所有用户来说,入口都是统一的。目前,官方还没有提供配置管理员id的操作。那么,如果要将一些管理页面整合到小程序中,鉴权操作是非常必要的。例如,在中大猫谱中,普通用户和管理员用户看到的页面元素、能进入的页面是不同的: [图片] 基于这种需求,本文将分享一种在微信·云开发环境下,实现简单、安全的后台鉴权的思路。 云函数实现 在描述方法前,我们先简单介绍一下微信·云开发的三大部件,分别是做啥用的: 云函数:后端的自定义的业务逻辑函数,自带Node.js环境。可以被小程序端调用,通常用于操作云存储和云数据库。拥有微信私有协议天然鉴权(后文重点使用)。 存储:类似云盘,存文件用的,自带CDN(流量不多)。它提供的[代码]cloud://[代码]协议文件链接可以直接用于部分小程序端tag上,比如image的src,但也就不会被缓存。 数据库:一个文档型数据库,可以被小程序端直接使用。权限设置比较迷(为了安全),大部分修改、删除操作要经过云函数来调用。 我们重点关注云函数。开通云开发后,新建一个云函数,我们会得到一个初始模板: [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() return { event, openid: wxContext.OPENID, // 调用者的openid,与每个微信号一一对应,用于鉴权 appid: wxContext.APPID, unionid: wxContext.UNIONID, } } [代码] 其中,云函数接受两个参数,[代码]event[代码]是用户调用时提供的data(可理解为形参),[代码]context[代码]是此处调用的调用信息和运行状态。幸运的是,这两个东西我们暂时都用不到,不理解也没有关系。 我们关注函数体的第一句[代码]cloud.getWXContext()[代码],它正是前文提到的微信私有协议天然鉴权。换人话说,这个函数返回的所有资料,都是有微信背书的、可信的。那么,最简单的鉴权方式,就是把管理员的openid硬编码到云函数中,对比一下就完成了: [代码]// isManager云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 硬编码管理员的openid const MANAGERS = ['aaaaaaa', 'bbbbbbb', 'cccccccc']; // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext(); const openid = wxContext.OPENID; // 取得当前用户openid return MANAGERS.includes(openid); // 完成鉴权 } [代码] 灵活一些 假如说我们的管理员常年不变,那上面那种鉴权方式完全够用了。但如果我们的管理员经常增删,那就利用云存储功能,建立一个[代码]manager[代码]集合(collection),把管理员的openid存放到文档中(听不明白请看下图)。那么上面硬编码的部分,就改为数据库查询: [代码]// isManager云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 初始化数据库链接 const db = cloud.database(); const _ = db.command; // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext(); const openid = wxContext.OPENID; // 查询条件 const filter = { openid: openid }; // 等待数据库查询 const count = (await db.collection('manager').where(filter).count()).total; // 检查是不是管理员 return (count === 1); } [代码] 现在管理管理员的方式(没打错字)更灵活了,可以直接打开小程序云开发控制台来添加/删除一个管理员。 [图片] 小程序端调用 在小程序端,我们可以简单包装一个鉴权函数,用callback的方式灵活地用在各种需要鉴权的地方: [代码]function checkManager(callback) { // 这里的callback将接受一个参数res, // 为bool类型,当前用户为manager时为true, // 否则为false // 调用云函数 wx.cloud.callFunction({ name: 'isManager', // 指明云函数的名字,没有形参 }).then(res => { // res是云函数的返回值,形如: // {errMsg: "cloud.callFunction:ok", result: true, requestID: "44b0xxxx-8xxx-xxxx-xxxx-xxxx0068xxxx"} // 其中的result字段是我们所需要的鉴权结果 callback(res.result); }); } [代码] 给定不同的回调函数,就可以简单地完成各种权限控制任务。例如,在某个Page的[代码]onLoad[代码]中控制元素显示: [代码]const that = this; checkManager(res => { if (res) { that.setData({ showBtns: true }); } }) [代码] 上面的鉴权操作,对非管理员用户的影响几乎没有。假如普通用户确实“闯进”了不该进入的页面,也可以简单地在上面加个else分支显示提示。 安全性分析 有了云函数的啥啥啥背书(微信私有协议天然鉴权),我们不用担心用户伪造openid的问题。但是,如果有中间人篡改了服务器发来的消息(说的就是你Mallory),小程序端获得的鉴权结果已经被修改了,那这种鉴权也不太可靠。因此,在一些关键的操作(例如数据库修改)上,鉴权和实际操作都应该放在后端云函数中,一条龙完成。 幸运的是,我们上面实现的[代码]isManager[代码]云函数仍可发光发热,被其他云函数调用。但是,间接调用的云函数无法获取调用者的OPENID(因为调用者不是一个微信用户,而是另一个云函数),我们要对上面的[代码]isManager[代码]函数进行一点点修改: [代码]// isManager云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 初始化数据库链接 const db = cloud.database(); const _ = db.command; // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext(); const openid = wxContext.OPENID || event.openid; // !! 只修改了这里:如果不能获取openid,就从参数event里取 // 查询条件 const filter = { openid: openid }; // 等待数据库查询 const count = (await db.collection('manager').where(filter).count()).total; // 检查是不是管理员 return (count === 1); } [代码] 其中修改只有一行:[代码]const openid = wxContext.OPENID || event.openid;[代码],这意味着如果[代码]cloud.getWXContext()[代码]函数返回的结果里不包含openid,那就从调用时给的参数[代码]event[代码]里取(说明当前调用是由其他云函数发起的)。 稍做修改后,在其他云函数中,只需在函数体最前面,增加以下几行,即可完成后端的安全鉴权: [代码]////// 省略一些初始化代码 ////// // 其他需要后端验证的云函数入口 exports.main = async (event, context) => { // 获取调用者的openid const wxContext = cloud.getWXContext(); const openid = wxContext.OPENID; // 用data参数的形式,把openid传给isManager云函数 const isManager = (await cloud.callFunction({ name: 'isManager', data: { openid: openid }})); // 如果不是管理员,直接886 if (!isManager.result) { return { msg: 'not a manager', result: isManager }; } ////// 下面放这个云函数要做的业务逻辑 ////// } [代码] 小总结 本文介绍了在微信小程序云开发环境下,利用云函数中微信背书的openid进行用户鉴权的一种思路。有了管理员鉴权接口、小程序端可以控制页面元素展示、路由访问、接口调用等情况,保护数据安全。目前小程序云开发的资料较少,本文也只是一种简单鉴权的实现思路,肯定还存在许多不足,希望大家多多交流、多多指正! 广告时间 今年上半年,中山大学四校区合拍的中大猫谱小程序正式开机,我们将与你一起继续扮演云吸猫爱好者、校园猫猫摄影大师、环境保护热心人士,希望大家多多关注,多多支持! 小程序演示视频请戳:https://v.qq.com/x/page/u0882tecle7.html [图片]
2019-06-28 - 给你的点击区域加个触控热区
一、背景 给图标(按钮、标签)做事件点击时,常常会因为元素面积太小导致用户很难点中,影响用户体验,产品大佬就会让我们做大点击区域,一般给元素加个padding:6rpx就可以了,但这时UI就会偏差。 二、无入侵扩大热区的方法 给需要增加热区的元素加上add_touch类,即可在原来的基础上,增加1.5倍触控热区。 .add_touch { position: relative; } .add_touch::after { content: ''; width: 100%; height: 100%; position: absolute; left: 0; top: 0; transform: scale(1.5); } 三、效果 [图片] 四、代码片段 https://developers.weixin.qq.com/s/ROoPyNme7dfK
2020-03-12