小程序实战三:本地数据存储及阿里云OSS备份(个人密码本示例)

本文主要是介绍小程序实战三:本地数据存储及阿里云OSS备份(个人密码本示例),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

功能描述

本次目标是制作一个密码记录工具,为保证私密性,数据保存在本地并通过直传方式备份到阿里云 OSS(需要用户开启自动备份并填写 AccessKeyID、AccessKeySecret)
代码详见:个人密码本

运行截图

  1. 用户编辑密码信息,包含类型(生活类、工作类、其他)、网站名称、登录名、密码(便于记忆的提示性文字)
  2. 小程序将数据保存到 Storage(默认明文,若设置了查看密码,则通过AES加密,此后需要用户输入密码才能查看)
  3. 若启用自动备份则将数据上传到阿里云 OSS

工具运行流程图如下:

工具流程图

相关知识

开始动手前,先了解下小程序中的数据存储

小程序文件系统

类型读权限写权限容量限制
Storage单个 KEY 上限 1M,总上限 10M
临时文件无限制
缓存文件与用户文件共计不超过 200M
用户文件与缓存文件共计不超过 200M

综上,开发者能够写数据的只有Storage本地用户文件,前者适合数据量小的场景。开发者可通过wx.getStoragewx.setStorage方法读写 Storage;通过 FileSystemManager 来管理用户文件。

此处我以 type = 0 表示Storage、type=1 表示用户文件,并对持久化数据读写进行了简单的封装(写方法执行成功后会触发自动备份子流程):

module.exports = {/*** 将数据保存到 storage,保存成功后触发自动备份* @param {*} key       若为空则自动根据当前页计算,命名方式为:{当前页名称}.{key}* @param {*} data      待保存的数据* @param {*} onOk      * @param {*} onFail */toStorage (key, data, onOk, onFail=defFailAct){key = !!key? key: util.buildUrlKey(key)console.debug(`保存到 Storage, key=`, key)wx.setStorage({ data, key, success: res=>{!onOk || onOk(res)//触发自动备份backup.onDataChange(key, 0)}, fail: onFail })},/*** 从 storage 加载数据* @param {*} key * @param {*} onOk  注意:若storage不存在,不执行该方法*/fromStorage (key, onOk){key = !!key? key: util.buildUrlKey(key)wx.getStorage({key, success:res=> !onOk || onOk(res.data)})},/*** 将数据写入到文件(将转换为 JSON 格式),保存成功后触发自动备份* @param {*} name * @param {*} data * @param {*} onOk * @param {*} onFail */toFile (name, data, onOk, onFail=defFailAct){let filePath = !!name? util.buildPath(name): buildFilePath(name)console.debug(`保存到文件,name=`, filePath)wx.getFileSystemManager().writeFile({filePath,data: JSON.stringify(data),success: d=>{!onOk || onOk(d)//触发自动备份backup.onDataChange(key, 1)},fail: onFail})},/*** 从文件中读取内容* @param {*} name      默认会以当前url* @param {*} onOk * @param {*} onFail */fromFile (name, onOk, onFail=defFailAct){let filePath = !!name? util.buildPath(name): buildFilePath(name)wx.getFileSystemManager().readFile({filePath,encoding:"utf8",success: res=>{!onOk || onOk(JSON.parse(res.data))},fail: onFail})}
}

相关示例:本地存储

功能实现

账号信息读取

_loadData (){store.fromStorage("", data=>{let items = undefined//如果以 [ 开头就是明文if(util.isJSONArrayText(data)){items = JSON.parse(data)}else {let needToInputPwd = trueif(aesKey){//尝试解密try{let rawText = aes.decrypt(aesKey, data)if(util.isJSONArrayText(rawText)){items = JSON.parse(rawText)needToInputPwd = false}}catch(decryptE){console.error(`解密数据出错:`, decryptE.message)}}if(needToInputPwd){if(!this.data.lockShow){//此处设置延迟执行,否则将出现 dialog 错误setTimeout(this.toLock, 200)}this.setData({needReload: true})return util.warn(`请输入查看密码`)}}if(Array.isArray(items)){if(this.data.keyword){items = items.filter(v=> `${v.site}${v.name}`.indexOf(this.data.keyword)>-1)}fixColor(items)this.setData({ items })}})
}

数据加解密

代码详见:utils/secret.js

const CryptoJS = require("./plugins/CryptoJS")
const md5 = require("./plugins/md5.min")const SALT = "WeappTools2020"
/*** AES 功能* 密钥为任意长度字符串(支持中文)* 密钥生成规则: md5("原始密钥+盐")*/
let aes = {iv: CryptoJS.enc.Utf8.parse('0604hxWeappTools'),buildKey (originText){let key = md5(`${originText}${SALT}`, SALT)return CryptoJS.enc.Utf8.parse(key)},encrypt (key, text){let encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(text), this.buildKey(key), {iv: this.iv, mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7})return encrypted.ciphertext.toString()},decrypt (key, encryptedText){let encryptedHexStr = CryptoJS.enc.Hex.parse(encryptedText)let decrypt = CryptoJS.AES.decrypt(CryptoJS.enc.Base64.stringify(encryptedHexStr), this.buildKey(key), {iv: this.iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7})return decrypt.toString(CryptoJS.enc.Utf8).toString()}
}

备份到 OSS

对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
阿里云有官方SDK ali-oss,但在小程序中无法正常使用,故这里使用的是 WEB 直传方式(也是官方推荐)

阿里云 OSS 官方文档: URL自签 、小程序直传

注意

  • 由于阿里云 OSS 每个 bucket 域名都不一致,小程序中需要配置域名白名单(不支持通配符)才能使用 request 访问,所以 bucket 此处必须为weapp-tools
  • 备份 Storage (type=0)类型数据时,先保存到用户文件,完成上传后删除该文件
  • 为区分 DEV 及线上环境,开发环境下备份文件将加上dev标识
let SETTING_PAGE = "pages/system/setting/setting"/*** @param {*} names     需要加载的配置项* @param {*} onOk      回调函数* @param {*} modal     配置项缺失时是否弹出前往配置页面的对话框* @param {*} prefix    配置项前缀,默认为空*/
let withSetting = (names, onOk, modal = false, prefix = "") => {let {config} = getApp().globalDatalet fields = names.map(n => config[`${prefix}${n}`])//检查为空let fieldSize = fields.filter(f => !!f).lengthif (fieldSize == fields.length) {onOk(...fields)} else if (modal) {wx.showModal({title: '未配置OSS',content: '请先到设置页面填写对象存储服务(Object Storage Service,OSS)相关参数才可使用该功能',confirmText: "前往设置",cancelText: "下次再说",confirmColor: "red",success: res => {if (res.confirm) {let pages = getCurrentPages()if (pages[pages.length - 1].route != SETTING_PAGE)this.jumpTo(SETTING_PAGE)}}})} elseconsole.debug(`[OSS] 配置项缺失,需要 ${names} 只找到 ${fieldSize} 个有效值...`)
}// 详细代码在:utils\oss\oss.js
/*** 阿里云 OSS 模块*/
let Aliyun = {keys: ["OSS_ALI_ID", 'OSS_ALI_SECRET', 'OSS_ALI_REGION'],config: {host: `https://weapp-tools.oss-cn-#region#.aliyuncs.com`,agent: "aliyun-sdk-js/6.9.0 Chrome 87.0.4280.67 on OS X 10.14.2 64-bit",timeout: 87600,                     // 文件失效时间region: "oss-cn-#region#",bucket: "weapp-tools",maxSize: 10 * 1024 * 1024       // 设置上传文件的大小限制(此处使用10M)},/*** 构建相关策略*/getPolicy() {let date = new Date();date.setHours(date.getHours() + this.config.timeout);let expire = date.toISOString();const policy = {"expiration": expire, // 设置该Policy的失效时间"conditions": [["content-length-range", 0,  this.config.maxSize] ]}return Base64.encode(JSON.stringify(policy));},// 用密钥对数据进行加密getSignature(policyBase64, secretKey) {const bytes = Crypto.HMAC(Crypto.SHA1, policyBase64,secretKey, {asBytes: true})return Crypto.util.bytesToBase64(bytes)},upload(filePath, targetPath, silent=true) {return new Promise((resolve, reject) => {withSetting(this.keys, (accessKeyId, accessKeySecret, region) => {let policy = this.getPolicy()console.debug(`[OSS Aliyun] 保存到 ${targetPath} policy=${policy}`)wx.uploadFile({url:    this.config.host.replace("#region#", region),filePath,name: 'file',formData: {'key':  targetPath, // 服务利用key找到文件'policy': policy,'OSSAccessKeyId': accessKeyId,'signature': this.getSignature(policy, accessKeySecret),'success_action_status': '200',},success: function (res) {if (res.statusCode != 200) {res.message = /<Message>(.+)<\/Message>/.exec(res.data)[1]reject(res)return}resolve({name: targetPath, server:"aliyun"}, res)},fail: err=> {err.wxaddinfo = this.config.hosterr.message = "微信接口 uploadFile 调用失败"reject(err)}})}, !silent)})}
}

写在最后

这次贴了好几段长代码(偷懒😂),而且是完整模块截取出来的,看起来会比较难受,有兴趣的朋友可以到github上查看完整代码。由于时间仓促代码可能有问题,如发现请联系我纠正。


往期文章

  1. 微信小程序开发基础(胎儿体重测算工具实例)
  2. 云函数开发及本地调试(意见反馈实例)

扫码或微信搜索集成工具集体验小程序 关注公众号
扫码(微信搜索集成工具集)体验小程序 / 关注公众号

这篇关于小程序实战三:本地数据存储及阿里云OSS备份(个人密码本示例)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/660641

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听