Springboot 系列 (13) - Springboot+Redis(二) | 使用 Lettuce 实现用户验证实例
Lettuce 是一个可扩展的线程安全 Redis 客户端,用于同步、异步和反应式使用。如果多个线程避免阻塞和事务性操作(如 BLPOP 和 MULTI/EXEC ),则它们可能共享一个连接。Lettuce 是基于 Netty 框架,支持高级 Redis 功能,如 Sentinel、群集、管道、自动重新连接和 Redis 数据模型。
本文使用 Redis 的 Lettuce 客户端实现用户验证实例。
Lettuce:https://lettuce.io/
Lettuce GitHub:https://github.com/lettuce-io/lettuce-core
1. 开发环境
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
注:Spring 开发环境的搭建,可以参考 “ Spring基础知识(1)- Spring简介、Spring体系结构和开发环境配置 ”。
2. 创建 Spring Boot 基础项目
项目实例名称:SpringbootExample13
Spring Boot 版本:2.6.6
创建步骤:
(1) 创建 Maven 项目实例 SpringbootExample13;
(2) Spring Boot Web 配置;
具体操作请参考 “Springboot 系列 (2) - 在 Spring Boot 项目里使用 Thymeleaf、JQuery+Bootstrap 和国际化” 里的项目实例 SpringbootExample02,文末包含如何使用 spring-boot-maven-plugin 插件运行打包的内容。
SpringbootExample13 和 SpringbootExample02 相比,SpringbootExample13 不导入 Thymeleaf 依赖包,也不配置 jQuery、Bootstrap、模版文件(templates/*.html)和国际化。
3. 配置 Lettuce
1) 修改 pom.xml,导入 Lettuce 依赖包
1 <project ... > 2 ... 3 <dependencies> 4 ... 5 6 <dependency> 7 <groupId>io.lettuce</groupId> 8 <artifactId>lettuce-core</artifactId> 9 <version>6.1.6.RELEASE</version> 10 </dependency> 11 12 ... 13 </dependencies> 14 15 ... 16 </project>
在IDE中项目列表 -> SpringbootExample13 -> 点击鼠标右键 -> 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/LettuceConfig.java 文件
1 package com.example.config; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Configuration; 5 import org.springframework.beans.factory.annotation.Value; 6 7 import io.lettuce.core.RedisURI; 8 import io.lettuce.core.RedisClient; 9 10 @Configuration 11 public class LettuceConfig { 12 @Value("${spring.redis.database}") 13 private Integer database; 14 @Value("${spring.redis.host}") 15 private String host; 16 @Value("${spring.redis.port}") 17 private Integer port; 18 @Value("${spring.redis.password}") 19 private String password; 20 @Value("${spring.redis.timeout}") 21 private Integer timeout; 22 @Value("${spring.redis.pool.max-active}") 23 private Integer maxActive; 24 @Value("${spring.redis.pool.max-idle}") 25 private Integer maxIdle; 26 27 @Bean 28 public RedisClient redisClientBean(){ 29 30 RedisURI redisUri = RedisURI.Builder.redis("localhost") 31 .withPort(port) 32 .withPassword(password) 33 .withDatabase(database) 34 .build(); 35 36 return RedisClient.create(redisUri); 37 } 38 39 }
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 io.lettuce.core.RedisClient; 9 import io.lettuce.core.api.StatefulRedisConnection; 10 import io.lettuce.core.api.sync.RedisCommands; 11 12 @Controller 13 public class IndexController { 14 @Autowired 15 private RedisClient redisClient; 16 17 @ResponseBody 18 @RequestMapping("/test") 19 public String test() { 20 21 StatefulRedisConnection<String, String> connection = redisClient.connect(); 22 RedisCommands<String, String> commands = connection.sync(); 23 24 String str = commands.get("lettuce"); 25 26 connection.close(); 27 //redisClient.shutdown(); 28 29 return "Test Page: " + str; 30 } 31 32 }
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 lettuce "Redis Lettuce Demo"
OK
(2) 测试
访问 http://localhost:9090/test,页面显示:
Test Page: Redis Lettuce Demo
4. 配置 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中项目列表 -> SpringbootExample13 -> 点击鼠标右键 -> 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 io.lettuce.core.RedisClient; 15 import io.lettuce.core.api.StatefulRedisConnection; 16 import io.lettuce.core.api.sync.RedisCommands; 17 18 @Configuration 19 public class RedisUserDetailsService implements UserDetailsService { 20 @Autowired 21 private RedisClient redisClient; 22 23 @Override 24 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 25 26 StatefulRedisConnection<String, String> connection = redisClient.connect(); 27 RedisCommands<String, String> commands = connection.sync(); 28 29 String password = commands.get(username); 30 31 connection.close(); 32 33 List<GrantedAuthority> authorities = new ArrayList<>(); 34 35 User userDetails= new User(username, password, authorities); 36 return userDetails; 37 } 38 }
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)无法登录。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)