当前位置: 首页 > news >正文

数据库修改密码风险高,如何保证业务持续,这几种密码双活方案可以参考

这是学习笔记的第 2147 篇文章


640?wx_fmt=gif

  今天下午的时候,有个朋友(感谢Crane.Chen氵)提了一个Oracle的问题,引起了我的好奇,问题的描述如下:

出于安全需要,这边的数据库密码必须90天更改一次,否则账号过期自动锁定。目前我们改密码都需要停掉应用,然后改密码后,启动应用。这样业务就会有中断。有什么方案可以保障即能更改密码,又能热更新应用里连接池的账号密码。现在若不停机,不管先更改连接池还是先改库,都可能因为密码不匹配而锁定账号。

   乍一看是个“不合理”的需求,数据库层面我们遵从安全规范来修改密码,我们照做就是了,但是显然做这个事情的成本实在太高,而且存在极高的风险,因为防御导致业务不可用带来的损失其实是很大的。 从一个层面来说,其实是孤立的看待了这个问题,只是考虑了自己,而没有考虑到应用层和全盘。做完自我批评,我来给出这个问题的一些解决之道。 

首先我们把这个密码修改的过程和应用层结合起来,应用层通常是使用连接池,而且主要是长连接的方式,如果修改了密码,那么会在数据库的字典配置里面修改密码信息,密码会在新的会话中立刻生效,但是已有的连接还是会保持,通常在业务层也是做了密码的配置文件,很可能看到的密码是一个加密串。

640?wx_fmt=png

所以最严重的的情况下无非是下面几种:

1)数据库先改密码,应用层后改,已有的长连接依旧可用,但是新连接失败,数据库密码错误超过3次,数据库账号就会被锁定,导致业务不可用。

2)应用层先改密码,数据库层后改,新连接会全部失败,错误密码超过3次,导致账号被锁定,业务不可用。

小结:从以上看出来,不管是什么样的顺序都会导致同样严重的后果,所以也就无所谓先后顺序了。 

而回到这个问题本身,我们可以做一些补救措施,我又了解了一些背景信息,这是使用weblogic中间件,通常这些配置都是启动时加载的,连接池目前我知道的还不支持动态热更新,所以要解决的重要问题是防止账号被锁定,数据库这边可以写一个脚本去实时检测账号的状态,如果被锁定,可以快速解锁, 这是一种不够优雅但是快速实用的解决方法。 

如果我们更近一步,从整个应用架构的层面来考虑,这个问题是否有解呢。 

我们来看下面的这个图:

640?wx_fmt=png

密码信息在应用层是配置形式,而且是启动自加载的模式,数据库密码是数据字典的基础信息,数据库层面是可以实时变化的,我们要保证业务的持续连接,一种方案就是建立影子账户,这个账户没有实际的数据,只有对等的权限,它平时处于锁定状态,即不可用。而应用层来建立连接的部分可以加一个动态的逻辑,如果连接失败,可以使用影子账户,这个影子账户的密码信息是约定好的,不会轻易发生改变,当需要修改密码的时候,可以按照如下的流程来操作:

  • 1)DBA解锁影子账户

  • 2)DBA修改账户密码

  • 3)应用层修改用户密码配置信息

  • 4)应用层分批次启动应用服务,使得配置生效

  • 5)DBA锁定影子账户

在这个过程中如果连接检测失败,会启用影子账户的来建立连接,在应用服务重启完成之后,就可以将影子账户锁定,应用层来再次动态适配,这样对于业务层来说就是一个动态平衡的过程。

其实对于很多公司来说,随着业务的快速变化,安全问题是挥之不去的隐患。所以密码修改也是一种合情合理的解决方式,当然在这个过程中会有一些可用性的影响,整体来说,我们要保证的是可控。

可能到了这里,我们才进行了一半,上面的方案应用层改造其实还是比较大的,而且对于权限的维护来说需要保证影子账户的权限也要完全一致,否则产生业务影响就很被动了。 

我们有没有更好的方案呢,其实最透明的方案是数据库层面来做好这种双层校验,这时我想到了MySQL 8.0的新特性。 

在MySQL 8.0.14的release note中是这么低调的一段描述。 

640?wx_fmt=png

我们通俗些可以理解为双密码,retain current password这个语法只在修改密码的场景中使用,在create user中是不能用的。意思是修改密码的时候原来的密码依旧可用,这样对于业务是最友好的方式。

正确理解这个语法的姿势是查看官方文档的解读:

640?wx_fmt=png

不演示一下不尽兴,我们来看看这个特性的效果。

首先创建一个用户:

mysql>  create user test_pwd identified by 'test_pwd1';	
Query OK, 0 rows affected (0.01 sec)

然后赋予一些基本的权限

mysql> grant usage on *.* to test_pwd ;	
Query OK, 0 rows affected (0.01 sec)

这个时候通过客户端连接是OK的。 

# mysql -utest_pwd -ptest_pwd1 -P33061 -h127.0.0.1	
mysql>

我们开始关键部分,修改用户密码,使用retain current password语法:

mysql> alter user test_pwd identified by 'test_pwd1' retain current password;	
ERROR 1227 (42000): Access denied; you need (at least one of) the CREATE USER or APPLICATION_PASSWORD_ADMIN privilege(s) for this operation

很遗憾失败了,因为这个操作是需要基本的权限的,根据提示需要APPLICATION_PASSWORD_ADMIN 或者CREATE USER的权限。

我们使用管理员账户修正下权限。

mysql> grant APPLICATION_PASSWORD_ADMIN on *.* to test_pwd;	
Query OK, 0 rows affected (0.01 sec)

再次修改就可以了。

mysql> alter user test_pwd identified by 'test_pwd2' retain current password; 	
Query OK, 0 rows affected (0.01 sec)

这个时候就达到了密码双活的状态,两个密码都可以用,而且校验始终都可用,幸福感大大增强。

当然我不建议对于业务无限制开放,毕竟这种方式会让双方都很难持续维护密码,所以在业务修改密码,批次启动应用服务后,我们可以回收原来的密码,使用discard old password子句。

mysql> alter user test_pwd DISCARD OLD PASSWORD;	
Query OK, 0 rows affected (0.01 sec)

这个时候连接会再次失败。

# mysql -utest_pwd -ptest_pwd1 -P33061 -h127.0.0.1      	
mysql: [Warning] Using a password on the command line interface can be insecure.	
ERROR 1045 (28000): Access denied for user 'test_pwd'@'localhost' (using password: YES)

这应该算是我们最希望看到的错误场景了,满满的完成任务的使命感。

期待MySQL 8.0更多更好的新特性。

640?wx_fmt=jpeg

近期热文:

相关文章:

  • MySQL业务双活的初步设计方案
  • 美女主持直播,被突发意外打断!湾区网友却高喊: 我懂!超甜
  • MySQL周期表管理太繁琐,通过Python自定义工具方法优雅解决
  • 千万不要养大型犬,多么痛的领悟
  • 《吊打面试官》系列-Redis基础
  • 为什么我们的数据科学团队无法产生价值
  • 在繁杂的业务需求中,如何找到API设计的平衡点
  • Greenplum的segment故障自愈小试
  • MySQL表添加了一个字段,竟然导致数据无法写入,反思
  • 通过Maxwell解析MySQL Binlog,打好业务多活的基础
  • 快到买买买的日子了,对于买书我提几点建议
  • 深度解读:我为什么从来不过“双十一”
  • 《黑客与画家》经典语录
  • 一个MySQL服务CPU 100%的优化案例反思
  • MySQL双主模式下是如何避免数据回环冲突的
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Druid 在有赞的实践
  • Js基础知识(四) - js运行原理与机制
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • learning koa2.x
  • Linux快速复制或删除大量小文件
  • MySQL主从复制读写分离及奇怪的问题
  • Netty 4.1 源代码学习:线程模型
  • session共享问题解决方案
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • Unix命令
  • Vue组件定义
  • 包装类对象
  • 测试开发系类之接口自动化测试
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 力扣(LeetCode)21
  • 两列自适应布局方案整理
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 你不可错过的前端面试题(一)
  • 配置 PM2 实现代码自动发布
  • 前言-如何学习区块链
  • 容器服务kubernetes弹性伸缩高级用法
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 《天龙八部3D》Unity技术方案揭秘
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #QT(一种朴素的计算器实现方法)
  • #数学建模# 线性规划问题的Matlab求解
  • (1)虚拟机的安装与使用,linux系统安装
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (4)logging(日志模块)
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (译) 函数式 JS #1:简介
  • .NET 材料检测系统崩溃分析