DataStore存储数据+加上加密

news2024/11/25 8:09:03

如果没有使用SP来存储数据,而是用datastore的话

但是datastore存储是个文件,所以我们需要再加密。

先展示没有加密的存储方式,然后再结合上一节的加密,再将存储的数据进行加密

使用datastore存储数据

添加依赖库

implementation "androidx.datastore:datastore-preferences:1.0.0"
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2'

定义数据类型

定义data class,添加 @Serializable 标签

@Serializable
data class UserSettings(
    val username: String? = null,
    val password: String? = null
)

定义Serializer

这里先展示没有加密的的序列化

存储的时候,将实例值转换成json string,再转换成bytearray写出到输出流,就可以保存到datastore的文件上了

读取的时候,从输入流中读取转成json string, 再通过json解析成 UserSetting实例

//继承datastore的Serializer,类型是我们定义的UserSettings
@RequiresApi(Build.VERSION_CODES.M)
class UserSettingsSerializer() : Serializer<UserSettings> {

    override val defaultValue: UserSettings
        get() = UserSettings()

    override suspend fun readFrom(input: InputStream): UserSettings {
        //将输入端的内容先转换成string
        //再将string通过json的解析再转换成UserSettings
        return try {
            Json.decodeFromString(
                deserializer = UserSettings.serializer(),
                string = inputStreamToByteArray(input).decodeToString()//decryptedBytes.decodeToString()
            )
        } catch(e: SerializationException) {
            e.printStackTrace()
            defaultValue
        }
    }

    private fun inputStreamToByteArray(inputStream: InputStream): ByteArray {
        val dataInputStream = DataInputStream(inputStream)
        val byteArrayOutputStream = ByteArrayOutputStream()

        val buffer = ByteArray(1024)
        var length: Int
        while ((dataInputStream.read(buffer).also { length = it }) != -1) {
            byteArrayOutputStream.write(buffer, 0, length)
        }

        return byteArrayOutputStream.toByteArray()
    }

    override suspend fun writeTo(t: UserSettings, output: OutputStream) {
        //把值为t的UserSettings,通过序列化转换成json string,再写出到输出流
        val bytes =Json.encodeToString(serializer=UserSettings.serializer(), value = t)
            .encodeToByteArray()
        output.write(bytes)

    }
}

初始化datastroe

datastore的文件名,传入我们前面定义的普通的序列化器UserSettingsSerializer,

定义的是Context.dataStore,这在Context中都可以访问到datastore。例如activity中就可以直接使用datastore

 private val Context.dataStore by dataStore(
        fileName = "user-settings.json",
        serializer = UserSettingsSerializer()
    )

跟新数据到datastore

                                dataStore.updateData {
                                    UserSettings(
                                        username = username,
                                        password = password
                                    )
                                }

读取数据

settings = dataStore.data.first()

直接就可以读取到 UserSetting类型的数据

查看文件

从data-data-packagename下可以看到文件

直接可以看到JSON格式的内容,这样就不是很安全,所以,存储到datastore中的内容需要加密

这个就连接上一篇中的AES加密

https://blog.csdn.net/github_35581409/article/details/142894715

只要对UserSettingsSerializer进行改造,在写入的时候,把JSON string进行加密

在读取的时候,先对string解密,然后再JSON解析

加密改造

添加加密管理

class UserSettingsSerializer(
    private val cryptoManager: CryptoManager //添加加密管理
) : Serializer<UserSettings>

写入

写入的时候,将实例值通过json编码,然后转换成byte。然后再通过cryptoManager进行加密,再写入输出流,输出流会把加密后的数据存储到datastore的文件中

    override suspend fun writeTo(t: UserSettings, output: OutputStream) {
        cryptoManager.encrypt(
            bytes = Json.encodeToString(
                serializer = UserSettings.serializer(),
                value = t
            ).encodeToByteArray(),
            outputStream = output
        )
//        val bytes =Json.encodeToString(serializer=UserSettings.serializer(), value = t)
//            .encodeToByteArray()
//        output.write(bytes)

    }

读取

把输入流中的内容,先进行解码,解码后的byte,在通过json组装成实例

    override suspend fun readFrom(input: InputStream): UserSettings {
        val decryptedBytes = cryptoManager.decrypt(input) //将输入流进行加密,生成加密后的bytes
        return try {
            Json.decodeFromString(
                deserializer = UserSettings.serializer(),
//                string = inputStreamToByteArray(input).decodeToString()
                decryptedBytes.decodeToString()
            )
        } catch(e: SerializationException) {
            e.printStackTrace()
            defaultValue
        }
    }

在datastore初始化的时候,补上加密管理器

   private val Context.dataStore by dataStore(
        fileName = "user-settings.json",
        serializer =UserSettingsSerializer(CryptoManager())
    )

再运行看看,加解密显示没有问题,

文件内容也变成了加密的了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2211968.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

心血之作!独家原创改进班翠鸟优化算法IPKO!2024年新算法!效果极佳!

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ ​历经数月&#xff0c;今天又给小伙伴们带了一期独…

IRP学习理解

IRP是Windows内核中的一种非常重要的数据结构。上层应用程序与底层驱动程序通信时&#xff0c;应用程序会发出I/O请求&#xff0c;操作系统将相应的I/O请求转换成相应的IRP&#xff0c;不同的IRP会根据类型被分派到不同的派遣例程中进行处理。 irp相当于R3下的消息&#xff0c…

【文档智能】文本文字识别、公式识别、表格文字识别核心算法及思路及实践-DBNet、CRNN、TrOCR

前言 OCR技术作为文档智能解析链路中的核心组件之一&#xff0c;贯穿整个技术链路&#xff0c;包括&#xff1a;文字识别、表格文字识别、公式识别&#xff0c;参看下面这张架构图&#xff1a; 前期介绍了很多关于文档智能解析相关核心技术及思路&#xff0c;本着连载的目的&a…

特斯拉“We, Robot“发布会:Robotaxi亮相,马斯克兑现承诺

在加利福尼亚州伯班克的华纳兄弟电影制片厂&#xff0c;特斯拉举办了以"We&#xff0c; Robot"为主题的发布会&#xff0c;这场活动吸引了全球科技爱好者的目光。特斯拉在此次发布会上展示了其在自动驾驶领域的最新突破&#xff0c;特别是公司CEO埃隆马斯克多年来承诺…

麒麟桌面版v10 SP1以docker方式安装达梦数据库

安装docker 0.切换root用户&#xff08;可以不切换&#xff0c;但要注意权限问题&#xff0c;我是用root&#xff09; ymym-pc:~/桌面$ whoami ym ymym-pc:~/桌面$ sudo -i rootym-pc:~# whoami root rootym-pc:~# 1.查看系统版本 [rootlocalhost opt]# cat /etc/os-release…

AI知识库如何提升服装电商的运营效率

随着人工智能技术的飞速发展&#xff0c;AI知识库在服装电商领域的应用日益广泛。AI知识库作为一个集成了海量数据、通过高级算法进行智能分析和处理的信息系统&#xff0c;正在深刻改变服装电商的运营模式和效率。本文将详细阐述AI知识库在商品信息管理、库存管理、订单处理等…

C语言题目练习4

这一篇博客继续在算法题的海洋里面遨游~ 链表的中间结点 链表的中间结点&#xff1a; https://leetcode.cn/problems/middle-of-the-linked-list/description/ 这个题我们可以怎么办呢&#xff1f;这里依然提供两个思路 思路1 既然是中间结点我们是不是可以直接第一次循环求…

MySQL从入门到跑路

SQL语言 SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是用于管理和操作关系数据库的一种标准编程语言。 SQL分类&#xff1a; DDL(Data Definition Language)&#xff1a;数据定义语言&#xff0c;用于操作数据库、表、字段&#xff0c…

天气API接口调用

天气API接口&#xff1a; 天气API接口是一种用于获取实时或预报天气信息的应用程序编程接口&#xff08;API&#xff09;。开发者可以使用这种接口在他们的应用程序或网站上集成天气查询功能&#xff0c;比如查询某个地区的当前温度、降水量、风速等数据。 通常&#xff0c;你…

Django ORM 进行基础 CRUD 操作(创建、读取、更新、删除)

Django ORM 进行基础 CRUD 操作&#xff08;创建、读取、更新、删除&#xff09; Django 是一个流行的 Python web 框架&#xff0c;提供了很多实用的功能来帮助开发者快速构建 web 应用程序。Django 的 ORM&#xff08;Object-Relational Mapping&#xff09;是其强大的数据库…

Java_ EE (网络编程)

网络编程基本概念: 计算机网络计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统。从其…

【C++算法】双指针

目录 一、快乐数&#xff1a; 二、有效三角形的个数&#xff1a; 三、盛最多水的容器&#xff1a; 四、复写0&#xff1a; 五、三数之和&#xff1a; 总结&#xff1a; 一、快乐数&#xff1a; 题目出处&#xff1a; 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09…

spring task的使用场景

spring task 简介 spring task 是spring自带的任务调度框架按照约定的时间执行某个方法的工具&#xff0c;类似于闹钟 应用场景 cron表达式 周和日两者必定有一个是问号 简单案例

基于java的企业车辆管理系统设计与实现(论文+源码)-kaic

摘 要 随着经济的日益增长,车辆作为最重要的交通工具,在企事业单位中得以普及,单位的车辆数目已经远远不止简单的几辆,与此同时就产生了车辆资源的合理分配使用问题。现有的车辆管理系统存在着不足之处&#xff0c;例如系统不够稳定&#xff0c;功能不够全面。因此&#xff0c…

Python基础之转义字符

字符串转义 转义是指在字符前加一个 \ \ n 则表示原来的字符n不代表字符n 赋予了一个新的含义 变成了一个换行符 print(wu\nzj\njing) \n 会解释为一个换行符 s "wu\"zj" 双引号是用来创建一个字符串的效果 加上\后就变成了一个字符双引号 它就是一个…

如何解决 Open /etc/postfix/main.cf: Permission denied ?

最近我的 Postfix 邮件系统无法发送电子邮件&#xff0c;报错内容&#xff1a;Open /etc/postfix/main.cf: Permission denied 经过一番调查&#xff0c;我能够解决这个问题。 日志文件中发现的错误如下&#xff1a; Jun 27 12:51:02 tecadmin postfix/postfix-script[11764]…

AI大模型开发架构设计(11)——AI 大模型与提示词工程助力职场典型案例场景实战

文章目录 AI 大模型与提示词工程助力职场典型案例场景实战1 AI大模型全局架构实战剖析AI大模型常见术语AI 大模型全局架构 2 Prompt Engineering 整体应用场景剖析Prompt 提示词的三个层次Prompt 提示词的经典模板如何让 Prompt 提示词做的更好?如何让 Prompt 提示词自动优化改…

ResNet模型

使用pytoch实现 1.卷积神经网络 conv2d的参数很简单 conv2d(input_channels, output_channels,kernel_size, stride, padding) 参数分别是输入通道&#xff0c;输出通道&#xff0c;卷积核大小&#xff0c;移动步长&#xff0c;填充数量。 输入通道是特征图的深度&#xff0c…

Android上的AES加密

基础算法说明 https://www.youtube.com/watch?vlnKPoWZnNNM 虽然这个视频讲的非常详细&#xff0c;但是涉及到具体底层算法&#xff0c;大致流程 1. 将数据转成HEX或者byte array 2.将数据分层一块块等大小的数据 3.将数据和key 进行一次混合&#xff0c;加密之后的输出&…

(vue)el-tabs标签页展示el-table动态表头表格

&#xff08;vue&#xff09;el-tabs标签页展示el-table动态表头表格 效果: 代码 <el-tabs v-if"showStatistics" type"border-card"><el-tab-panev-for"(item, index) in statisticsTable":key"index":label"item.pr…