记录移动开发初探——用uniApp+sqlite仿XyKey实现密码管理记事本

写在前面

最近刚准备上手移动开发,本着想要多端可用的原则,了解到了uniApp。大致扫完一遍文档,基本可以算是vue+微信小程序原生,对我来说基本0难度可直接进入开发。因此想着索性做一款简单的app来做更加深入的了解。就在这时候,朋友给我推了XyKey这个应用,在使用了一番之后,还是非常有兴趣的,于是打算自己仿XyKey开发一个类似的密码管理记事本。

注:

我自己开发的这个项目灵感来源于:聊一聊我是怎么设计 XyKey,界面UI设计也是仿照XyKey来的。XyKey可在安卓市场免费下载,苹果商店12元可购买,相比较之下我的项目只是仿写,实现了核心功能,但一些优化用户体验的功能我没有做,毕竟我的目的只是研究uniApp。还请大家支持正版。如果本文有涉及任何权益问题请联系我进行删除。

思路

既然是要实现密码管理,那肯定要有数据库存放数据。但对我来说,作为一个后端小白,对于数据库的认知仅仅停留在一些简单的增删改查语句,因此使用mysql,搭建服务器等都是一个难题。而且对于密码管理来说,如果把密码存在服务器的数据库里,也会有被盗取的风险。

这个时候,就要用到sqlite了。

关于sqlite,本文不做过多的介绍了,补一个百科的链接,有需要的小伙伴可以自行百度:百度百科 - sqlite

那么,用到了sqlite之后,我们其实就可以实现纯前端开发一个完整的简单移动应用了。

而在uniApp中要使用sqlite也很简单,只要在manifest.json文件中,在App模块权限配置下勾选sqlite数据库就可以了,非常的方便。

在这里插入图片描述
如果用其他编辑器打开这个文件找不到这个界面的,请使用HbuilderX进行开发。当然在源码里也可以添加代码实现对sqlite的支持,但这个可视化界面更为友好,并且开发完之后也可以直接用Hbuilder打包下载安装。

那么至此,准备工作就做完了,接下来正式进入开发。

最重要考虑的就是安全性方面了。对于普通的应用来说,第一就是用户隔离,也就是你要区分使用者是不同的人,拥有他们自己的数据。这就涉及到了登陆功能,让用户设置一个只有自己知道的登录密码和账号,只有正确之后才可以对自己保存的数据进行操作。但这一点对于sqlite来说没有任何的意义,因为它是嵌入式的,不存在说你的数据库里存着别人的数据。不过,即使这样,我们也不能完全没有限制,像备忘录那样随意使用,这样安全性会很不好。

因此,我一开始的思路就是,还是要建一张user表,只是这里面只有一条数据,就是用户在第一次使用的时候设置的密码。等用户以后使用时,再让用户输入密码,然后和这个设置好的密码进行比对,正确就可以正常使用,不正确就无法使用。

但显而易见的是,这根本就是多此一举。我专门建了一张表,就这么一条数据,然后每次用的时候都要去查一遍,然后比对,正确了才给用,不正确还不给用,非常的不高级,不漂亮。

也是这个时候我才看到本文开篇贴的那个,XyKey设计者谈他的设计思路的那篇文章(其实这时因为我先开发了别的页面和功能,整个项目已经基本开发完,在收尾了。但看到这篇文章之后我受到了很多启发,于是又调整了许多我自己的代码来加入这些思路),于是我就看到了他文章里关于开放式挂载的想法,这让我眼前一亮。

是啊,本身所谓的登录密码,用户体验差不说,在这个情况下也没有任何的意义,干脆去掉算了。可能这时有人就会问了,你刚才不是说,去掉之后,不能保证数据的安全性吗?

其实这里的去掉,并不是完全去掉登录时输入密码这一步,而是不建表去保存,直接把这个作为关键的key。这一点我们可以利用AES的加密解密。关于AES加密,本文也不做过多的展开了,按惯例补一下百科链接:百度百科 - aes

那么,在进行aes加密和解密的时候,是需要一个key作为密码的。如果这个解密时的密码和加密时的密码不一样,解密就会失败。

于是思路就很明显了。用户在刚打开这个应用的时候,还是要输入一个密码。只是这个密码我不会去专门建一张表保存它,而是直接定义一个全局变量存放它。然后,当我需要加密的时候,我就直接使用这个全局变量作为加密时的key,然后存放到数据库里。这个全局变量的值会因为你退出应用而消失。

关键代码:
1.将输入框中的值存入userPwd变量

that.userPwd = e.detail.value;

2.将userPwd存入全局变量

getApp().globalData.userPwd = that.userPwd;

3.加密时,把这个全局变量作为加密的key。注意,这里一开始我直接将密码作为key,但发现解密的时候解不出来,后来我发现这个key一定是要16位的。我本来限制了输入框小于等于16位,所以处理了一下,当用户输入的key不足16位的时候,用a补满,补满之后加密解密正常。

encrypt(word, keyStr) {
	var extraZero = "";
	if (getApp().globalData.userPwd) {
		var num = 16 - getApp().globalData.userPwd.length;
		for (var i = 0; i < num; i++) {
			extraZero += "a";
		}
	}
	var defaultKeyStr = getApp().globalData.userPwd.length != 16 ? getApp().globalData.userPwd + extraZero : getApp().globalData.userPwd;
	keyStr = keyStr ? keyStr : defaultKeyStr;
	var key = CryptoJS.enc.Utf8.parse(keyStr); 
	var srcs = CryptoJS.enc.Utf8.parse(word);
	var encrypted = CryptoJS.AES.encrypt(srcs, key, {
		mode: CryptoJS.mode.ECB,
		padding: CryptoJS.pad.Pkcs7
	});
	return encrypted.toString();
}

这样,用户每次使用这个应用,这个全局变量的值都是全新输入的,而每次需要解密的时候,我都再去读取当前的这个全局变量的值来解密。注意,这个时候,因为用户每一次输入的不一定是上一次加密的时候输入的那个key,所以一旦输入不一致,就无法解出之前保存的密码,实现了登陆功能一样的效果。

关键代码(加密解密其实只是encrypt和decrypt的区别):

decrypt(word, keyStr) {
	...	//这里就不重复写了
	var decrypt = CryptoJS.AES.decrypt(word, key, {
		mode: CryptoJS.mode.ECB,
		padding: CryptoJS.pad.Pkcs7
	});
	return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}

并且,正如XyKey设计者说的那样,这样设计的好处是,用户不管输入什么都可以使用应用了,不会被挡在外面。同时,由于在输入错误的key解不出真正的密码时,他看到的是加密后的数据,也能让他清楚地知道自己的密码数据是被加密了保存的,这让他在使用时更加放心。并且,每个加密的key对应的数据都是独立的,用户可以自由的决定哪个key可以看到哪些密码,极大地提高了可扩展性。

页面预览:

我自己开发的项目中,我也对分类做了一些自己的处理。XyKey是没法增加或者删除分类的,只能修改已有分类。我认为这里可扩展性不够,因此我开发时,规定分类至少要有一个,并且只有在此分类下没有保存的密码数据时,我才允许删除这个分类。我允许用户新建分类,也会在一开始给一个叫默认的分类,当然这个默认的分类也是可以被修改名字和被删除的。

页面预览:

关于建表的话,我是建了一张account表存放密码数据,一张type表存放分类数据。本来还建了一张extra表用于存放新增密码数据时的自定义新内容(也就是在新建密码数据时,除了我写好的一些必填的内容,用户也可以按自己想要的去新增一项然后填写自己想记录的内容,这个无论是数量还是具体内容都是很自由的,所以单独建一张表存放,然后用id绑到对应数据上),但因为这里不作深入展开了,所以暂时搁置,等真正要完善这个项目的用户体验时再完成。

至此,核心功能的思路就差不多讲完了。

补一下uniApp执行SQL语句的代码:

executeSQL(sql, successCallback, failCallBack) {
	var that = this;
	plus.sqlite.executeSql({
		name: 'chrisPWNoteDB',
		sql: sql,
		success: function(data) {
			console.log('executeSql success!' + JSON.stringify(data));
			if (successCallback) {
				successCallback(data);
			}
		},
		fail: function(e) {
			console.log('executeSql failed: ' + JSON.stringify(e));
			if (failCallBack) {
				failCallBack(e);
			}
		}
	});
}

和点击复制文字内容的方法:

copyText() {
	var that = this;
	if(that.clipBordText){
		uni.setClipboardData({
			data: that.clipBordText
		});
	}
}

其他看了看也没什么特别要交代的了,都是uniApp开发文档里现成的内容,就不搬来搬去了。源码本来是放在github上的,但考虑到因为是仿写别人的项目,就暂时没有公开。有想要研究的可以问我要。我也可以直接打个安卓包给你(苹果暂时不行),然后你自己去下载Xykey比较一下使用体验。

后话

uniApp是可以直接使用scss的哦,不需要额外安装插件!当然这里对于scss也不展开讲了,但它提供的变量、嵌套、混合、继承等特性,懂的都懂!(我快写完了才发现的,改了一小部分,懒得再改了,说多了都是泪)

补一下

有小伙伴私信我说,你这个虽然用的是uniApp,但你用sqlite的话,也就只能用在安卓端和ios端,各平台小程序和h5都不支持。

对于这个问题,我想说这位小伙伴说的没错,但我是这样想的,首先对于这个项目而言,他的功能决定了它比较适合成为一个本地应用,而不是像小程序或h5那样在浏览器上,去联网(联网就有被窃取数据的风险)。

其次就是,这也是我刚刚接触移动开发,其实本身就比较偏向用uniApp去代替安卓原生和ios原生来开发移动APP,只要安卓和ios能通用就算完成目标,毕竟我本身对原生小程序开发还是比较熟悉的,小程序端的项目不太需要用uniApp来完成(我也会用mpvue,但这个吧我个人不太爱)。

当然后面有时间了也会专门用uniApp去开发一个多平台通用的小程序,那就是后话了。

感谢小伙伴给我的反馈,后面我也会尽量讲清楚的~

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UniApp是一个跨平台的应用开发框架,它结合了Vue.js和微信小程序的开发方式,可以快速高效地开发出可在iOS、Android和H5平台运行的应用程序。 SQLite是一种轻量级嵌入式数据库系统,可以实现存储和管理大量结构化数据,具有高效、稳定和可靠等特点。 问卷系统是一种常见的调查工具,用于收集用户对特定话题或事件的观点和反馈。 在UniApp使用SQLite作为问卷系统的后台数据库可实现一些重要功能,包括问卷的创建和设计、问题的录入和编辑、用户答卷的收集和统计等。 首先,开发者可以利用UniApp的跨平台特性,在一个代码库中开发出同时适用于iOS、Android和H5平台的问卷系统应用。这样可以大大提高开发效率,减少维护成本。 其次,SQLite作为嵌入式数据库,无需独立的服务器环境,可以直接嵌入UniApp应用中,使得问卷系统具备离线访问和本地存储的能力。用户可以在无网络环境下填写问卷,当网络可用时自动同步数据至服务器。 另外,SQLite提供了强大的数据查询和统计功能,可以方便地进行答卷数据的分析和报告生成。开发者可以利用UniApp提供的页面和组件,实现直观、美观的数据展示和用户界面。 最后,UniApp还支持调用设备的硬件接口和系统功能,可以利用手机摄像头、定位、推送等功能与问卷系统进行集成,提供更丰富、更个性化的问卷体验。 综上所述,利用UniAppSQLite开发问卷系统可以快速高效地实现跨平台、离线可用、数据分析和设备集成等功能,提供全面的问卷调查解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值