IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 浅析数据产品中数据源密码的安全管理设计与实现 -> 正文阅读

[网络协议]浅析数据产品中数据源密码的安全管理设计与实现

概述

最近在全职负责一款数据产品,从后端研发,到前端研发(半吊子),到测试验证(近乎全职),到产品功能交互等设计(又是半吊子),几乎只有我一个人。之所以是这样的局面,是因为被具备中国特色社会主义的公司老板压榨着。

设计

功能浅析

世面上的数据产品,很多很多。其中有不少产品,都大体上可以理解为,基于数据源,提供数据处理,数据监控,推送与可视化的产品。我负责的就是这样一款产品。

显然数据源是一切功能的基础。

界面设计粗略一窥,左侧菜单栏如下图,其中数据源是核心:
在这里插入图片描述
数据源列表页:
在这里插入图片描述
某个数据源的操作功能如下:
在这里插入图片描述
新增,查看,编辑数据源,共用同一个模态框,下图中mongo数据源类型其实也是jdbc中一种:
在这里插入图片描述
数据源类型有:
在这里插入图片描述
其中:

  1. 分享与审批是与权限相关的;
  2. 查看,编辑,删除,没啥好说;
  3. 复制,提供快捷参考复制其他数据源的功能。

需要注意的是,为了避免数据源的反复创建,设计一条数据源唯一性规则:url + username + password。

密码加密

本文的核心是密码的安全管理。常规的列表接口都是原样存储数据到数据表,然后近乎原样以列表形式返回,前端展示一个表格组件。

绝大多数数据产品里,前端控件都会对密码进行mask处理,但对于稍微具备一点点Chrome开发知识的人来说,都知道开发者模式,即打开F12(或右键,检查)点击Network,查看请求的RequestBody和responseBody,responseBody里面即是数据源密码,这就意味着密码有泄露的风险。

解决方案,不难想到加密处理:

  1. 加密操作由后端来实现,对返回给前端的数据,过滤password字段,加密返回给前端;
  2. 后续需要前后端交互的场景,如上图中点击联通测试,需要前端传输用户名,密码等信息给后端;
    1. 如果是新增数据源,传输给后端的密码是原始密码;
    2. 如果是编辑数据源,但是不更新密码,而是更新数据源名称等其他信息,则传输给后端的应该是加密后的密码;
    3. 如果是编辑数据源更新密码,则传输给后端的是原始密码。

所以问题来了:后端无法判断编辑更新情况下,前端传过来的密码是明文还是密文,需不需要解密。

加密问题

对于如上加解密问题。稍加思考后,想到一个可行的方案,有一定的折衷退步思考意味。方案如下:列表页返回的是加密后的密码。如果是查看或编辑某个数据源,则前端调用后端新增提供的获取数据源详情接口,此接口返回的数据是明文,也就是常规接口设计,前后端交互流程。

值得一提的是:在我们这个数据产品中,查看或编辑某个数据源这个权限并不是暴露出来的,需要申请并审批通过之后方可生效。满足安全性要求。

也就是说,用户可以看到数据源列表页概要信息,名称,创建人,创建时间,修改人,修改时间,负责人,最机密的信息是连接串,通过Chrome开发者模式,可以看到数据源用户名,但是看到的密码是加密处理的。

总结:数据库存储的数据是明文;交互流程:

  1. 列表页展示时,后端加密处理,控制台只能看到;
  2. 新增数据源时,输入明文,保存明文;
  3. 数据源查看时,无需加密处理,
  4. 数据源编辑时,无需加密处理,

优化

数据库存储加密?

代码片段

PageHelper.startPage(params.getInteger("pageNo"), params.getInteger("pageSize"));
if (StringUtils.isNotBlank(params.getString("sortField"))) {
    params.put("sortField", StringUtil.camelCaseToUnderscore(params.getString("sortField")));
}
List<DashboardDatasource> lists = datasourceMapper.findDataSourceByParams(params);
for (DashboardDatasource item : lists) {
    item.setConnectionStr(this.getConnectionStr(item.getConfig()));
    JSONObject config = JSONObject.parseObject(item.getConfig());
    // 存在密码时才加密(Redis无密码)
    if (StringUtils.isNotBlank(config.getString("password"))) {
        config.put("password", DecodeUtil.encrypt(config.getString("password")));
    }
    item.setConfig(config.toJSONString());
}
public String testConnection(JSONObject dataSource) {
    try {
        /*JSONObject config = dataSource.getJSONObject("config");
        // 新增数据源时无需解密
        if (!dataSource.getString("modalType").equals("add")) {
            // 解密一定要trim()
            config.put("password", DecodeUtil.desEncrypt(config.getString("password")).trim());
        }*/
        dataProvider.checkConnection();
        return JSONObject.toJSONString(ServiceUtil.returnSuccess());
    } catch (Exception e) {
        logger.error("datasource test error", e);
        return JSONObject.toJSONString(ServiceUtil.returnError(e.getMessage()));
    }
}

参考

Java String加解密踩坑

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-05-14 10:12:53  更:2022-05-14 10:14:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 5:05:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码