展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

记住我

案例一:github/03/security/demo04

  • 在demo03的基础上继续开发
# core模块将ValidateCodeException提取到exception文件夹

# core模块导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

# web模块配置数据源
spring:
  # 数据源配置
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
    #mysql8版本以上驱动包指定新的驱动类
    driver-class-name: com.mysql.cj.jdbc.Driver

# SpringSecurityConfig中添加如下
@Autowired
DataSource dataSource;

@Bean
public JdbcTokenRepositoryImpl jdbcTokenRepository() {
    JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
    jdbcTokenRepository.setDataSource(dataSource);
    // 是否启动项目时自动创建表,true自动创建,如果数据库中已经生成了persistent_logins表,则需要设为false,否则会报错
    jdbcTokenRepository.setCreateTableOnStartup(true);
    return jdbcTokenRepository;
}

.and()
.rememberMe() // 记住功能配置
.tokenRepository(jdbcTokenRepository()) //保存登录信息
.tokenValiditySeconds(60*60*24*7) //记住我有效时长

# 创建对应数据库
demo

# 前端添加如下
<input name="remember-me" type="checkbox" id="remember">记住我
  • 测试
# 获取验证码
08:43:37.204  INFO 18196 --- [nio-8080-exec-1] c.y.s.a.core.ImageCodeValidateFilter     : session中的验证码为:null
08:43:37.205  INFO 18196 --- [nio-8080-exec-1] c.y.s.a.core.ImageCodeValidateFilter     : 登录时输入的验证码为:null
08:43:37.220  INFO 18196 --- [nio-8080-exec-1] c.y.s.controller.CustomLoginController   : 生成的图形验证码是:ebc3
# 认证时
08:44:08.023  INFO 18196 --- [nio-8080-exec-6] c.y.s.a.core.ImageCodeValidateFilter     : session中的验证码为:null
08:44:08.023  INFO 18196 --- [nio-8080-exec-6] c.y.s.a.core.ImageCodeValidateFilter     : 登录时输入的验证码为:ebc3
08:44:08.023  INFO 18196 --- [nio-8080-exec-6] c.y.s.a.core.ImageCodeValidateFilter     : session中的验证码为:null
08:44:08.023  INFO 18196 --- [nio-8080-exec-6] c.y.s.a.core.ImageCodeValidateFilter     : 登录时输入的验证码为:ebc3
# 没有获取到session中的验证码
  • 解决方案:将验证码存入redis
# core模块添加依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

# redis配置类
@Configuration
public class LettuceRedisConfig {
    @Bean
    public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }
}

# redis工具类
@Component
public class RedisUtils {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    /**
     * 设置key-value
     * @param key 键
     * @param value 值
     */
    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }
    /**
     * 设置带生存时间的key-value
     * @param key 键
     * @param value 值
     * @param timeout 生存时间
     * @param unit 时间单位
     */
    public void set(String key, String value, long timeout,     TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }
    /**
     * 设置指定数据的生存时间。
     * @param key 键
     * @param time 生存时间(秒)
     */
    public void expire(String key, long time) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }
    /**
     * 根据key,获取值
     * @param key 键
     * @return 获取到的值
     */
    public String get(String key) {
        return String.valueOf(redisTemplate.opsForValue().get(key));
    }
    /**
     * 删除指定信息。
     * @param key 键
     * @return 是否删除成功
     */
    public boolean delete(String key) {
        return redisTemplate.delete(key);
    }
}

# 修改获取验证码的接口
    @RequestMapping("/code/image")
    public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. 获取验证码字符串
        String code = defaultKaptcha.createText();
        logger.info("生成的图形验证码是:" + code);
        // 2. 将验证码放到redis中
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        operations.set(SESSION_KEY , code);
        // 3. 获取验证码图片
        BufferedImage image = defaultKaptcha.createImage(code);
        // 4. 将验证码图片把它写出去
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
    }

# 修改过滤器中的逻辑
    private void validate(HttpServletRequest request) {
        // 先获取seesion中的验证码
//        String sessionCode =
//                (String)request.getSession().getAttribute(CustomLoginController.SESSION_KEY);
        // 获取用户输入的验证码
        String inpuCode = request.getParameter("code");
        // 获取redis中的验证码
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        String redisCode = operations.get(SESSION_KEY);;
        //logger.info("session中的验证码为:" + sessionCode);
        logger.info("登录时输入的验证码为:" + inpuCode);
        logger.info("redis中的验证码为:" + redisCode);
        // 判断是否正确
        if(StringUtils.isBlank(inpuCode)) {
            throw new ValidateCodeException("验证码不能为空");
        }
        if(!inpuCode.equalsIgnoreCase(redisCode)) {
            throw new ValidateCodeException("验证码输入错误");
        }
    }

# web模块配置yml
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    # password: 没有不用写
    lettuce:
      # 连接池配置
      pool:
        # 连接池中的最小空闲连接,默认 0
        min-idle: 0
        # 连接池中的最大空闲连接,默认 8
        max-idle: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制),默认 -1ms
        max-wait: -1ms
        # 连接池最大连接数(使用负值表示没有限制),默认 8
        max-active: 8
  • 测试
# 获取验证码
09:46:30.656  INFO 5924 --- [nio-8080-exec-1] c.y.s.controller.CustomLoginController   : 生成的图形验证码是:5nbn
# 认证
09:46:53.144  INFO 5924 --- [nio-8080-exec-3] c.y.s.service.CustomUserDetailsService   : 请求认证的用户名: admin
09:47:07.077  INFO 5924 --- [nio-8080-exec-4] c.y.s.a.core.ImageCodeValidateFilter     : 登录时输入的验证码为:5nbn
09:47:07.078  INFO 5924 --- [nio-8080-exec-4] c.y.s.a.core.ImageCodeValidateFilter     : redis中的验证码为:5nbn
  • 认证
  • 不能跳转到指定页面

案例二:github/03/security/demo05

  • 在demo01的基础上开发
# core模块将ValidateCodeException提取到exception文件夹

# core模块导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

# web模块配置数据源
spring:
  # 数据源配置
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
    #mysql8版本以上驱动包指定新的驱动类
    driver-class-name: com.mysql.cj.jdbc.Driver

# SpringSecurityConfig中添加如下
@Autowired
DataSource dataSource;
@Bean
public JdbcTokenRepositoryImpl jdbcTokenRepository() {
    JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
    jdbcTokenRepository.setDataSource(dataSource);
    // 是否启动项目时自动创建表,true自动创建
    jdbcTokenRepository.setCreateTableOnStartup(false);
    return jdbcTokenRepository;
}

.and()
.rememberMe() // 记住功能配置
.tokenRepository(jdbcTokenRepository()) //保存登录信息
.tokenValiditySeconds(60*60*24*7) //记住我有效时长

# 创建对应数据库
demo

# 前端添加如下
<input name="remember-me" type="checkbox" id="remember">记住我

# 测试
GET http://localhost:8080/code/image HTTP/1.1

POST http://localhost:8080/login?username=admin&password=admin&code=x88f HTTP/1.1

# 测试通过

posted @ 2022-06-24 08:46  DogLeftover  阅读(12)  评论(0编辑  收藏  举报