Spring 系列 (12) - Springboot+Redis(一) | 使用 Jedis 實現使用者驗證例項
Redis 是一個開源(BSD許可)的,記憶體中的資料結構儲存系統,可以用作資料庫、快取和訊息中介軟體。
Redis 支援多種型別的資料結構,如 字串(strings)、雜湊(hashes)、 列表(lists)、集合(sets)、 有序集合(sorted sets)與範圍查詢、bitmaps、hyperloglogs 和 地理空間(geospatial)索引半徑查詢。
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 的 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 配置;
具體操作請參考 “Spring 系列 (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=8
spring.redis.pool.max-idle=8
spring.redis.pool.max-wait=-1
spring.redis.sentinel.master=
spring.redis.sentinel.nodes=
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)無法登入。