windows下载地址 https://github.com/microsoftarchive/redis/releases/download/win-3.0.504/Redis-x64-3.0.504.msi
安装后redis服务默认会启动
SDS simple dynamic string
SDS是redis底层使用的字符串结构
1 2 3 4 5 6 7 8 9 struct sdshdr { int len; int free ; char buf[]; };
保留了\0
字符,目的是为了复用c语言中的字符串方法
buf.length = len + 1 + free
其中free为每次分配空间进行的预分配内存,避免每次扩展字符串时都需要重新申请空间。以1M为限,1M下会分配即将用到的内存的两倍,1M以上只多分配1M,避免指数爆炸。当然如果free本身就能够支持本次操作,则不会进行内存重分配。
free空间为惰性释放,当对字符串进行缩短操作时,会将回收的内存放在free中而不是会立即释放,便于后续使用,同时SDS提供了对应的释放api避免造成内存浪费。
此外,SDS为二进制安全的,由于不会通过终止符判断是否到信息结尾,故可以存储二进制数据即使其中包含\0
,保证数据在存储与读取时的一致性
链表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 typedef struct listNode { struct listNode * prev ; struct listNode * next ; void * value; }listNode; typedef struct list { listNode * head; listNode * tail; unsigned long len; void *(*dup)(void *ptr); void (*free )(void *ptr); int (*match)(void *ptr,void *key); } list ;
双向无环链表,带头指针和尾指针,且带链表长度,同时结点的值为void指针类型,故具有多态性。
字典 RedisTemplate 使用 spring默认提供的redisTemplate并不好用,这里使用自定义的RedisTemplate<String, Object>
redis连接 1 2 3 4 5 6 spring: redis: database: 0 host: 127.0 .0 .1 port: 6379 connect-timeout: 1000
redis配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Configuration public class RedisConfig { @Bean(name = "myTemplate") public RedisTemplate<String,Object> template (RedisConnectionFactory factory) { RedisTemplate<String ,Object> template = new RedisTemplate <>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer <Object>(Object.class); ObjectMapper om = new ObjectMapper (); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer (); template.setKeySerializer(stringRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Autowired RedisTemplate<String,Object> myTemplate; @GetMapping("/factory") public Object factoryInfo () throws JsonProcessingException { ValueOperations<String, Object> stringObjectValueOperations = myTemplate.opsForValue(); Student student = new Student (); student.setName("掌上" ); student.setAge(18 ); student.setGender("男" ); student.setStudentNum("201806010145" ); stringObjectValueOperations.set("ms" ,student); Object value = stringObjectValueOperations.get("ms" ); System.out.println(value); return value; }
EnableRedisRepositories 使用 实体类配置 指定实体类中的id,并将实体类加@RedisHash(“student”)的注解,将会以student:id为key的方式存入redis
1 2 3 4 5 6 7 8 @RedisHash("student") public class Student { @Id Long id; String name; Integer age; String gender; String studentNum;
Dao与Service Dao
1 2 3 @Repository public interface StudentDao extends CrudRepository <Student, Long> {}
泛型中第一位为存储类型,第二位为id的类型
Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @Service public class StudentService { @Autowired private StudentDao studentDao; public void save (Student student) { studentDao.save(student); } public Student findOne (Long id) { Student student = studentDao.findById(id).get(); return student; } }
调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Autowired StudentService studentService; @GetMapping("/rep/student/{id}") public Object saveAndGetStudentByRep (@PathVariable Long id) throws JsonProcessingException { Student student = new Student (); student.setName("掌上" ); student.setAge(18 ); student.setGender("男" ); student.setStudentNum(LocalDateTime.now().toString()); studentService.save(student); Student value = studentService.findOne(id); System.out.println(value); return value; }
保护模式 redis默认开启保护模式。要是配置里没有指定bind和密码,开启该参数后,redis只能本地访问,拒绝外部访问。
redis.conf安全设置: # 打开保护模式 protected-mode yes
Redis 的保护模式是一种安全特性,它限制了 Redis 服务器的访问权限。当保护模式被启用时,如果没有设置 bind
参数和密码,Redis 服务器将只接受来自本地主机的连接。这意味着,外部客户端将无法连接到 Redis 服务器,除非它们在同一个局域网内或具有相应的权限。
具体来说:
bind 参数 :bind
参数用于指定 Redis 服务器应该绑定的 IP 地址。如果未设置此参数,Redis 将绑定到所有可用的网络接口。但当保护模式被启用时,如果未设置 bind
参数,Redis 将只接受来自 localhost(127.0.0.1)的连接。
密码 :为了从外部访问 Redis,你可以设置密码。当保护模式被启用时,如果你没有设置密码,外部客户端将无法连接到 Redis 服务器,除非它们具有适当的权限或位于相同的局域网内。
因此,当 Redis 的保护模式被启用且没有设置 bind
和密码时,Redis 服务器的访问将被限制在本地机器上。这有助于增强服务器的安全性,防止未经授权的访问。
禁用或者重命名危险命令 Redis中线上使用keys *命令是非常危险的,应该禁用或者限制使用这些危险的命令,可降低Redis写入文件漏洞的入侵风险。
KEYS *
命令在 Redis 中用于列出所有的键。当 Redis 服务器正在处理这个命令时,它会遍历整个键空间,这可能会导致长时间的阻塞,尤其是在有大量数据的情况下。
更糟糕的是,如果有外部攻击者恶意地使用 KEYS *
命令,它可能会导致 Redis 服务器资源耗尽,从而拒绝服务。
修改 redis.conf 文件,添加
1 2 3 4 5 6 7 rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command CONFIG "" rename-command KEYS "" rename-command SHUTDOWN "" rename-command DEL "" rename-command EVAL ""
然后重启redis。 重命名为”” 代表禁用命令,如想保留命令,可以重命名为不可猜测的字符串,如:rename-command FLUSHALL joYAPNXRPmcarcR4ZDgC
启用远程连接 修改redis.conf文件,linux在/etc/redis下
修改protcted-mode为false
将bind一行注释
requirepass 后面设置密码
启用密码后的cli连接 redis-cli之后,需要使用 auth password 进行认证,否则无权限操作
远程:redis-cli -h host -p port -a password
Hash过期 hash类型数据无法为单独的每条数据设置过期时间,只能为整个hash结构设置过期时间,如果有需求,建议在单个字段中存储过期时间手动判断
日志记录 linux下redisc.onf
文件在etc的redis下面,编辑该文件,找到logfile一行,改行为日志文件所在地址
redis被攻击记录 redis关掉了保护模式与bind,密码设为了123456
现象,redis在备份rdb文件时出错,显示日志如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 * 1 changes in 900 seconds. Saving... * Background saving started by pid 2127220 * DB saved on disk * RDB: 0 MB of memory used by copy-on-write * Background saving terminated with success // 备份文件夹只读 # Failed opening the RDB file root (in server root dir /var/spool/cron) for saving: Read-only file system # Failed opening the RDB file redis (in server root dir /var/spool/cron) for saving: Read-only file system // 不知道哪里来的MASTERR * Connecting to MASTER 108.181.122.221:60101 * MASTER <-> REPLICA sync started * Non blocking connect for SYNC fired the event. * Master replied to PING, replication can continue... * Trying a partial resynchronization (request ccc31f7f854cd2e74e324a89c50f5e9d244d31e5:1). * Full resync from master: ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ:0 * Discarding previously cached master state. * MASTER <-> REPLICA sync: receiving 21816 bytes from master
其中奇怪的地方,一个是出现了一个主机,另一个是备份文件夹变成了只读
首先没有配置过主从复制,其次查看配置文件中,备份文件夹的地址为 /var/lib/redis
,可见配置被动态修改了
参考攻击方法:Redis攻防(未授权访问、利用redis写入webshell、任务计划反弹、Shellssh-keygen 公钥登录服务器、利用主从复制RCE)_redis未授权访问写入webshell的步骤不包括?(1.00分) 设置数据缓存文件 设置数据缓-CSDN博客
建议配置方式
单独为redis设置一个普通账号启动 redis
设置本地 localhost 不允许外部访问
保护模式开启 protected-mode 开启 (默认开启)
把端口最好更改
requirepass 设置redis密码
好在使用apt安装的redis,且使用systemctl启动redis,这样redis的所属用户为redis,没有系统文件夹比如进程等的操作权限
systemctl启动redis的配置 使用systemctl start redis
命令启动Redis服务时,默认情况下会以redis
用户的身份运行。这是通过systemd
的单元文件来配置的,该文件定义了服务的运行方式。
要查看Redis服务的用户配置,可以执行以下步骤:
打开Redis服务的单元文件。在大多数Linux发行版上,Redis服务的单元文件位于/etc/systemd/system/redis.service
或/lib/systemd/system/redis.service
。
使用文本编辑器打开该文件。
在文件中查找User
行。该行指定了运行Redis服务的用户。它应该类似于以下内容:
如果你想更改运行Redis服务的用户,只需将User
行中的值修改为你想要的用户名,并保存文件。
重新加载systemd
配置并重新启动Redis服务,以使更改生效。可以使用以下命令:
1 2 sudo systemctl daemon-reload sudo systemctl restart redis
请注意,更改运行Redis服务的用户需要具有适当的系统权限,并且确保新的用户具有访问Redis所需的文件和目录的权限。此外,确保在更改用户配置之前备份原始的单元文件,以便在需要时可以还原。