【Redis深度专题】「踩坑技术提升」一文教会你如何在支持Redis在低版本Jedis情况下兼容Redis的ACL机制

news2025/1/16 21:59:23

Redis低版本客户端兼容高版本Jedis不支持ACL的问题

首先,针对于Redis6.0之后,已经可以支持通过ACL的访问控制列表的机制进行控制多个用户进行权限控制访问,并且更加精细的控制权限访问处理模式,更加的偏向于RBAC模型的机制体系。

Redis的ACL是什么?

Redis的ACL(Access Control List)是一种用于访问控制的功能,它允许您对Redis服务器进行细粒度的权限管理和访问控制。通过使用ACL,您可以限制对Redis命令和数据的访问,以保护您的Redis实例免受未经授权的访问和滥用。

Redis的ACL功能提供了以下几个关键方面的控制:

  1. 用户和角色管理:ACL允许您创建和管理多个用户,并为每个用户分配适当的角色。角色定义了用户可以执行的命令和访问的数据范围。

  2. 命令级别的权限控制:您可以为每个角色指定允许执行的命令和禁止执行的命令。这使您能够限制用户对特定命令的访问权限。

  3. 数据级别的权限控制:ACL还允许您为每个角色指定可以访问的数据库和键空间。这使您能够限制用户对特定数据的访问权限。

  4. 密码和认证:ACL允许您为每个用户设置密码,并要求用户在连接到Redis服务器时进行身份验证。这提供了一种基本的身份验证机制,以确保只有经过身份验证的用户才能访问Redis。

通过使用ACL,您可以实现对Redis的细粒度访问控制,确保只有经过授权的用户才能执行特定的命令和访问特定的数据。这有助于提高Redis实例的安全性,并防止未经授权的访问和滥用。

POC调研计划方案

目前公司存在了某种需求问题,需要进行调整和升级Redis版本,并且倾向于通过用户(可以理解为角色)+ 密码的方式进行对于Redis访问的控制。

poc截止到了现在应该是勉强可以了,不过还有一些问题,但是应该是可以实现了,大概使用了4套方案:

  1. 升级整体框架版本整体框架,从而升级客户端版本,后面发现和代码的适配问题会引发很多不必要的坑,以及后续改动量实在太大了,我大概POC花费了2d时间去处理。

  2. 不修改整体框架版本,只修改单纯的客户端版本,我修改了很多源码,以及对应的客户端底库,最后发现对于集群模式的时候会出现很多问题,而且DBS目前才有的应该是集群模式吧,所以暂时放弃了,大概POC花费了1d时间

  3. 升级客户端底层仓库,不修改客户端以及框架,后面我也是在减少项目代码的变化,然后将jedis的底层源码进行修改了,但是发现了发现可以实现,但是改动量实在是太大了,基本上修改了整体的源码仓库才可能性,而且出现了对于so库的仓库的加载的问题,POC花费了2d,工作l量至少需要1w人天。

4. (推荐)全流成改造我们的项目代码,方便所有的redisson和jedis代码进行改造和优化调整,以及jedis的对应兼容acl的用户名认证的代码,以及添加对应的配置实现,并且加入适配的代码即可,从而可以实现对应的对应的兼容ACL模式下的:用户名和密码登录。POC花费了2d,工作量还是比较大,我预测大概至少3-4d的实现改造所有服务的代码(1d)的时间进行自测。

Jedis升级版本功能实现控制

Jedis源码改造原则

在不改造任何版本框架版本的场景下,仅仅进行使用适配的模型和能力进行实现用户名和密码的登陆方式。其中就要用到一个原则就是项目目录与jar包中的文件相同的全限定名的时候,会优先采用项目目录中的类进行加载,从而我们就获得了进行覆盖jedis源码的能力。

覆盖Auth的Jedis操作认证

我们将整个BinaryClient全部拷贝出来,放到我们的项目里面,并且包名必须为:redis.clients.jedis。

面向的类为:redis.clients.jedis.BinaryClient。在较低版本的源码为:

 public void auth(final String password) {
         setPassword(password);
         sendCommand(AUTH, password);
 }

对此,我们需要进行对于高版本的代码变更一下Redis的指令auth从参数角度进行变更即可。

指令修改和代码调整兼容

auth password

变更为支持用户名+密码的认证模式机制

auth userName password

故此我们将代码修改为:

 public void auth(final String password) {
        String userName = RedisUserName.redisUserName;
        if(StringUtils.isNotBlank(userName)){
            setPassword(password);
            sendCommand(AUTH,userName, password);
        }
        else {
            setPassword(password);
            sendCommand(AUTH, password);
        }
  }

此外还考虑了兼容单独密码的模式,所以进行调整了兼容两种模式都共存的if语句,嘻嘻。
在这里插入图片描述

这样子将底层的功能进行直接获取用户名进行控制,减少了很多的开发量问题。并且对于Spring框架、甚至我们自己的框架都是透明化的问题。

Redis用户名的传输和配置

接下来就是最后一个问题,配置用户名以及如何传递给他,我在这里使用了一个简单的方案就是通过静态变量进行传输。方便我们全局访问!

在这里插入图片描述

从下面的配置可以看到,我们属于使用RedisUserName类进行访问此类的redisUserName变量进行访问。那么这个值是怎么来的?

直接上源码干货

不说太多其他的,直接上干货即可。

@Component
public class RedisUserName implements BeanPostProcessor {

    public static String redisUserName;

    @Value("${spring.redis.userName:root}")
    private String userName;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof RedisConfig && StringUtils.isEmpty(redisUserName)){
            RedisUserName.class.getClassLoader();
            try {
                Class.forName(RedisUserName.class.getName());
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            RedisUserName.redisUserName = userName;
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof RedisConfig && StringUtils.isEmpty(redisUserName)){
            RedisUserName.class.getClassLoader();
            try {
                Class.forName(RedisUserName.class.getName());
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            RedisUserName.redisUserName = userName;
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

实现了Spring的BeanPostProcessor接口的类的方法。它的作用是在Bean初始化之前对特定的Bean进行处理。

  1. public static String redisUserName;:定义了一个静态的字符串变量redisUserName,用于存储Redis的用户名。

  2. @Value("${spring.redis.userName:root}"):使用Spring的@Value注解,将配置文件中的spring.redis.userName属性的值注入到userName变量中。如果配置文件中没有配置该属性,则默认值为"root"。

  3. postProcessBeforeInitialization方法:这是BeanPostProcessor接口的一个方法,用于在Bean初始化之前进行处理。在这个方法中,首先判断当前处理的Bean是否是RedisConfig类型,并且redisUserName为空。如果满足条件,则执行以下操作:

    • RedisUserName.class.getClassLoader();:这行代码没有实际作用,可能是作者误写或者遗留的无用代码。

    • Class.forName(RedisUserName.class.getName());:通过反射加载RedisUserName类,这行代码也没有实际作用,可能是作者误写或者遗留的无用代码。

    • RedisUserName.redisUserName = userName;:将userName的值赋给redisUserName静态变量,即将配置文件中的spring.redis.userName属性的值赋给redisUserName变量。

  4. 最后,返回BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);,继续执行其他的BeanPostProcessor的处理逻辑。

总结介绍说明

在RedisConfig类的Bean初始化之前,将配置文件中的spring.redis.userName属性的值赋给静态变量redisUserName。这样可以在其他地方通过访问RedisUserName.redisUserName来获取Redis的用户名。但是代码中的部分内容,如RedisUserName.class.getClassLoader();Class.forName(RedisUserName.class.getName());似乎没有实际作用,可能是作者误写或者遗留的无用代码。

修改配置和调整控制

设置对应的ACL的用户和设置指令

主要用于对应SAAS环境的中用户和我们Redis的ACL是一个概念的用户设计。

增加配置文件中的key或者环境变量

# 主要用于Jedis客户端的连接使用
spring.redis.userName: {用户名}
# 主要用于Redisson客户端的连接使用
redisson.userName: {用户名}

修改对应的配置信息

spring.redis.password:{你在设置ACL的时候所制定的密码}

设置Redis的ACL用户指令

设置用户密码

ACL SETUSER {用户名} on >{你的密码}

设置用户整体操作权限

> acl setuser {用户名} ~* &* +@all

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

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

相关文章

【非root用户、CentOS系统】中使用源码安装gcc/g++的教程

1.引言 系统:CentOS-7.9 显卡驱动版本:460 CUDA Version: 11.2 🌼基于本地环境选择安装gcc-10.1.0 👉 gcc下载网址 2.安装说明 下载好对应的gcc的安装包并解压: 打开gcc-10.1.0/contrib/download_prerequisites&#…

《视觉 SLAM 十四讲》V2 第 8 讲 视觉里程计2 【如何根据图像 估计 相机运动】【光流 —> 直接法】

OpenCV关于 光流的教程 文章目录 第 8 讲 视觉里程计 28.2 光流8.3 实践: LK 光流 【Code】本讲 CMakeLists.txt 8.4 直接法8.5 实践: 双目的稀疏直接法 【Code】8.5.4 直接法的优缺点 习题 8√ 题1 光流方法题2题3题4题5 第 8 讲 视觉里程计 2 P205 …

vue3脚手架搭建

一.安装 vue3.0 脚手架 如果之前安装了2.0的脚手架,要先卸载掉,输入: npm uninstall vue-cli -g 进行全局卸载 1.安装node.js(npm) node.js:简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是…

Linux高性能服务器编程——ch2笔记

第2章 IP 协议详解 2.1 IP服务的特点 无状态:IP通信双方不同步传输数据的状态信息。IP数据报相互独立,缺点是无法处理乱序和重复的IP数据报。上层协议如果是面向连接的协议(TCP),能够自己处理乱序和重复的报文段。IP…

【Leetcode】 707. 设计链表

你可以选择使用单链表或者双链表,设计并实现自己的链表。 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。 如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点…

英语——分享篇——每日200词——1201-1400

1201——wound——[wu:nd]——n.伤口,创伤——wound——wo我(拼音)un联合国(编码)d狗(编码dog)——我在联合国治好了狗的伤口——The nurse cleaned the wound .——护士清洗了伤口。 1202——from——[frɒm]——prep.来自,从,由于——from—…

正点原子嵌入式linux驱动开发——pinctrl和gpio子系统

在上一篇笔记中,学习编写了基于设备树的LED驱动,但是驱动的本质还是没变,都是配置LED灯 所使用的GPIO寄存器,驱动开发方式和裸机基本没区别。Linux是一个庞大而完善的系统,尤其是驱动框架,像GPIO这种最基本…

C++11 正则表达式详解

目录 1 正则表达式语法1.1 字符和特殊字符1.2 限定符1.3 定位符1.4 选择和反向引用 2 C正则表达式标准库常用接口3 C正则表达式模板的使用3.1 匹配(Match)3.2 搜索(Search)3.3 分词(Tokenize)3.4 替换&…

【前端学习】—ES6新增的方法有哪些(十五)

【前端学习】—ES6新增的方法有哪些(十五) 一 、ES6中新增的方法 (一)、Object.is() //用于判断两个值/数据类型是否相等/* 特点:不仅可以对值类型进行正常处理,对象类型的值也可以处理对于特殊的值NaN 也…

分享一下怎么做多门店小程序

近年来,随着互联网的普及和移动支付的兴起,越来越多的商家开始涉足线上业务,开发自己的小程序。对于拥有多家门店的连锁品牌来说,开发多门店小程序是一个非常不错的选择。本文将围绕多门店小程序的制作展开讨论,希望能…

阿里8年经验之谈 —— 如何选择合适的自动化测试工具?

自动化测试是高质量软件交付领域中最重要的实践之一。在今天的敏捷开发方法中,几乎任一软件开发过程都需要在开发阶段的某个时候进行自动化测试,以加速回归测试的工作。自动化测试工具可以帮助测试人员以及整个团队专注于自动化工具无法处理的各自任务&a…

【网络安全 --- XSS绕过】xss绕过手法及思路你了解吗?常见及常用的绕过手法了解一下吧

本次博客以pikachu靶场为例,需要安装靶场可以参考以下博客(都包含工具,镜像下载地址) 一,工具资源下载 1-1 VMware虚拟机的安装 请参考以下博客,包含资源下载地址(若已安装请忽略)…

2023年知名国产数据库厂家汇总

随着信创国产化的崛起,大家纷纷在寻找可替代的国产数据库厂家。这里小编就给大家汇总了一些国内知名数据库厂家,仅供参考哦! 2023年知名国产数据库厂家汇总 1、人大金仓 2、瀚高 3、高斯 4、阿里云 5、华为云 6、浪潮 7、达梦 8、南大…

基于java网上书城系统的设计与实现

1 绪 论 网上书城系统采用了一种ssm的开发框架。讨论该系统的需求分析,将系统分为两大模块。前台模块由五部分功能组成,而后台模块则由八部分功能组成。作为网上书城系统,它的设计目的是改变传统的图书销售模式,迎合当代主流需…

acwing算法基础之数据结构--KMP算法

目录 1 知识点2 模板 1 知识点 KMP算法已经集成到string类型的find()方法了, 但这里我们不用这个,我们自己来实现这个方法。 KMP算法的关键步骤: p[N]表示输入模式串,求取该模式串的ne[]数组。ne[i]表示前缀等于后缀的长度&…

电压放大器在电子实验中有哪些作用

电压放大器在电子实验中扮演着重要的角色,它可以实现对电压信号的放大,为实验提供所需的电压级别。下面是电压放大器在电子实验中的几个常见作用: 信号放大:电压放大器的主要作用是将输入信号的幅度放大,以便进行更准确…

AXI总线协议

总线:总线是传输数据的通道,由各种逻辑器件构成,一般由数据线、地址线、控制线等构成 接口:连接标准,又称之为物理接口i 协议:传输数据的规则 什么是AXI AXI(Advanced Extensible Interfece)是高级可扩展…

ModelCenter—多学科设计优化软件

产品概述 Ansys ModelCenter是美国Ansys公司旗下的一款产品,用于赋能工程师创建和自动化多工具工作流,优化产品设计。ModelCenter是一个创新的软件框架,可以灵活地满足基于模型的需求工程。在ModelCenter框架内工作,工程师能够将…

GDPU 数据结构 天码行空5

一、实验目的 1.掌握队列的顺序存储结构 2.掌握队列先进先出运算原则在解决实际问题中的应用 二、实验内容 仿照教材顺序循环队列的例子,设计一个只使用队头指针和计数器的顺序循环队列抽象数据类型。其中操作包括:初始化、入队…

安全典型配置(四)使用自反ACL实现单向访问控制案例

【微|信|公|众|号:厦门微思网络】 安全典型配置(一)使用ACL限制FTP访问权限案例_厦门微思网络的博客-CSDN博客 安全典型配置(二)使用ACL限制用户在特定时间访问特定服务器的权限-CSDN博客 安全典型配置&#xff0…