Springboot 系列 (12) - Springboot+Redis(一) | 使用 Jedis 实现用户验证实例
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件。
Redis 支持多种类型的数据结构,如字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、 有序集合(sorted sets)、基数估计算法(HyperLogLog)等。
Redis 优势:
(1) 性能极高 - Redis 能读的速度是 110000 次/s,写的速度是 81000 次/s;
(2) 丰富的数据类型 - Redis 支持二进制的 Strings、Lists、Hashes、Sets 及 Ordered Sets 数据类型操作;
(3) 原子 - Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来;
(4) 丰富的特性 - Redis 还支持 publish/subscribe、通知、key 过期等特性。
Redis 官方对 Java 语言的封装框架推荐中,Jedis、Lettuce、Redisson 是三种比较常用的 Redis Java 客户端。其中,Jedis 的方法调用是比较接近于底层的 Redis 的 API,也即 Jedis 的 Java 方法基本和 Redis 的 API 保持了一致,了解 Redis 的 API,也就能熟练的使用 Jedis。
本文使用 Redis 的 Jedis 客户端实现用户验证实例。
Redis: https://github.com/redis
Jedis: https://github.com/redis/jedis
1. Redis 安装配置
1) Windows 下安装
https://github.com/tporadowski/redis/releases,本文下载 Redis-x64-5.0.14.1.msi 直接安装(安装后自动运行),熟悉 Windows 命令的也可以下载 *.zip 包配置运行。
启动一个 cmd 窗口,运行如下命令。
C:\> redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> ping
PONG
以上命令表示 Redis 客户端已经连接上 Redis 服务器。
2) Ubuntu 下安装
(1) apt 命令安装
安装 Redis 运行如下命令
$ sudo apt update
$ sudo apt install redis-server
启动 Server
$ redis-server
启动 Client
$ redis-cli
redis 127.0.0.1:6379> ping
PONG
(2) 源码安装
https://download.redis.io/releases/,本文下载了 redis-5.0.14.tar.gz。
下载编译
$ wget https://download.redis.io/releases/redis-5.0.14.tar.gz
$ tar -vxzf redis-5.0.14.tar.gz
$ cd redis-5.0.14
$ make
启动 Server
$ cd src
$ ./redis-server
启动 Client
$ ./redis-cli
redis 127.0.0.1:6379> ping
PONG
3) 设置密码
可以通过以下命令查看是否设置了密码:
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) ""
默认情况下 requirepass 参数是空的,可以通过以下命令来设置密码:
127.0.0.1:6379> CONFIG set requirepass "123456"
OK
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) "123456"
设置密码后,客户端连接 redis 服务就需要密码验证。
127.0.0.1:6379> AUTH "123456"
OK
2. 开发环境
Windows版本:Windows 10 Home (20H2)
IntelliJ IDEA (https://www.jetbrains.com/idea/download/):Community Edition for Windows 2020.1.4
Apache Maven (https://maven.apache.org/):3.8.1
Redis for Windows:5.0.14
注:Spring 开发环境的搭建,可以参考 “ Spring基础知识(1)- Spring简介、Spring体系结构和开发环境配置 ”。
3. 创建 Spring Boot 基础项目
项目实例名称:SpringbootExample12
Spring Boot 版本:2.6.6
创建步骤:
(1) 创建 Maven 项目实例 SpringbootExample12;
(2) Spring Boot Web 配置;
具体操作请参考 “Springboot 系列 (2) - 在 Spring Boot 项目里使用 Thymeleaf、JQuery+Bootstrap 和国际化” 里的项目实例 SpringbootExample02,文末包含如何使用 spring-boot-maven-plugin 插件运行打包的内容。
SpringbootExample12 和 SpringbootExample02 相比,SpringbootExample12 不导入 Thymeleaf 依赖包,也不配置 jQuery、Bootstrap、模版文件(templates/*.html)和国际化。
4. 配置 Jedis
1) 修改 pom.xml,导入 Jedis 依赖包
1 <project ... > 2 ... 3 <dependencies> 4 ... 5 6 <dependency> 7 <groupId>redis.clients</groupId> 8 <artifactId>jedis</artifactId> 9 <version>4.0.1</version> 10 </dependency> 11 12 ... 13 </dependencies> 14 15 ... 16 </project>
在IDE中项目列表 -> SpringbootExample12 -> 点击鼠标右键 -> Maven -> Reload Project
2) 修改 src/main/resources/application.properties 文件,添加如下配置
# redis
spring.redis.database=0
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=123456
spring.redis.timeout=5000
spring.redis.pool.max-active=10
spring.redis.pool.max-idle=10
spring.redis.pool.max-wait=-1
spring.redis.sentinel.master=
spring.redis.sentinel.nodes=
注:max-wait 使用负值表示没有限制(或称无穷大)
3) 创建 src/main/java/com/example/config/JedisConfig.java 文件
1 package com.example.config; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.beans.factory.annotation.Qualifier; 5 import org.springframework.context.annotation.Configuration; 6 import org.springframework.beans.factory.annotation.Value; 7 8 import redis.clients.jedis.JedisPool; 9 import redis.clients.jedis.JedisPoolConfig; 10 11 @Configuration 12 public class JedisConfig { 13 @Value("${spring.redis.database}") 14 private Integer database; 15 @Value("${spring.redis.host}") 16 private String host; 17 @Value("${spring.redis.port}") 18 private Integer port; 19 @Value("${spring.redis.password}") 20 private String password; 21 @Value("${spring.redis.timeout}") 22 private Integer timeout; 23 @Value("${spring.redis.pool.max-active}") 24 private Integer maxActive; 25 @Value("${spring.redis.pool.max-idle}") 26 private Integer maxIdle; 27 28 @Bean 29 public JedisPoolConfig jedisPoolConfig(){ 30 31 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); 32 jedisPoolConfig.setMaxTotal(maxActive); 33 jedisPoolConfig.setMaxIdle(maxIdle); 34 return jedisPoolConfig; 35 } 36 37 @Bean 38 public JedisPool jedisPool(@Qualifier("jedisPoolConfig")JedisPoolConfig jedisPoolConfig){ 39 40 JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 41 timeout, password, database); 42 43 return jedisPool; 44 } 45 46 }
4) 修改 src/main/java/com/example/controller/IndexController.java 文件
1 package com.example.controller; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 import org.springframework.web.bind.annotation.ResponseBody; 7 8 import redis.clients.jedis.JedisPool; 9 import redis.clients.jedis.Jedis; 10 11 @Controller 12 public class IndexController { 13 @Autowired 14 private JedisPool jedisPool; 15 16 @ResponseBody 17 @RequestMapping("/test") 18 public String test() { 19 20 Jedis jedis = jedisPool.getResource(); 21 String str = jedis.get("redis"); 22 23 return "Test Page: " + str; 24 } 25 26 }
5) 运行
(1) 创建 Redis Key
启动一个 cmd 窗口,运行如下命令。
C:\> redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> AUTH "123456"
OK
127.0.0.1:6379> SET redis "Redis Jedis Demo"
OK
(2) 测试
访问 http://localhost:9090/test,页面显示:
Test Page: Redis Jedis Demo
5. 配置 Security
1) 修改 pom.xml,导入 Security 依赖包
1 <project ... > 2 ... 3 <dependencies> 4 ... 5 6 <!-- Spring security --> 7 <dependency> 8 <groupId>org.springframework.boot</groupId> 9 <artifactId>spring-boot-starter-security</artifactId> 10 </dependency> 11 12 ... 13 </dependencies> 14 15 ... 16 </project>
在IDE中项目列表 -> SpringbootExample12 -> 点击鼠标右键 -> Maven -> Reload Project
2) 修改 src/main/resources/application.properties 文件,添加如下配置
# security
spring.security.user.name=admin
spring.security.user.password=123456
spring.security.user.roles=admin
运行并访问 http://localhost:9090/test,自动跳转到 http://localhost:9090/login (Spring security 的默认页面),输入上面的用户名和密码登录,登录后跳转到 http://localhost:9090/test。
3) 创建 src/main/java/com/example/service/RedisUserDetailsService.java 文件
1 package com.example.service; 2 3 import java.util.List; 4 import java.util.ArrayList; 5 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.context.annotation.Configuration; 8 import org.springframework.security.core.userdetails.User; 9 import org.springframework.security.core.userdetails.UserDetails; 10 import org.springframework.security.core.userdetails.UserDetailsService; 11 import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 import org.springframework.security.core.GrantedAuthority; 13 14 import redis.clients.jedis.JedisPool; 15 import redis.clients.jedis.Jedis; 16 17 @Configuration 18 public class RedisUserDetailsService implements UserDetailsService { 19 @Autowired 20 private JedisPool jedisPool; 21 22 @Override 23 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 24 25 Jedis jedis = jedisPool.getResource(); 26 String password = jedis.get(username); 27 28 List<GrantedAuthority> authorities = new ArrayList<>(); 29 30 User userDetails= new User(username, password, authorities); 31 return userDetails; 32 } 33 }
4) 创建 src/main/java/com/example/config/WebSecurityConfig.java 文件
1 package com.example.config; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.context.annotation.Configuration; 6 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 7 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 8 //import org.springframework.security.core.userdetails.UserDetailsService; 9 import com.example.service.RedisUserDetailsService; 10 import org.springframework.security.crypto.password.NoOpPasswordEncoder; 11 import org.springframework.security.crypto.password.PasswordEncoder; 12 13 @Configuration 14 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 15 @Autowired 16 //private UserDetailsService userDetailsService; 17 private RedisUserDetailsService redisUserDetailsService; 18 19 @Override 20 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 21 //auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); 22 auth.userDetailsService(redisUserDetailsService).passwordEncoder(passwordEncoder()); 23 } 24 25 @Bean 26 public PasswordEncoder passwordEncoder(){ 27 return NoOpPasswordEncoder.getInstance(); 28 } 29 }
5) 运行
(1) 创建 Redis Key
启动一个 cmd 窗口,运行如下命令。
C:\> redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> AUTH "123456"
OK
127.0.0.1:6379> SET user "user"
OK
(2) 测试
运行并访问 http://localhost:9090/test,自动跳转到 http://localhost:9090/login (Spring security 的默认页面),输入用户/密码: user/user,登录后跳转到 http://localhost:9090/test。
注:此时 application.properties 里设置的用户/密码(admin/123456)无法登录。