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)无法登录。


posted @ 2022-05-22 21:08  垄山小站  阅读(412)  评论(0)    收藏  举报