案例一:github/03/security/demo04
| |
| |
| |
| <dependency> |
| <groupId>org.springframework.boot</groupId> |
| <artifactId>spring-boot-starter-jdbc</artifactId> |
| </dependency> |
| <dependency> |
| <groupId>mysql</groupId> |
| <artifactId>mysql-connector-java</artifactId> |
| </dependency> |
| |
| |
| spring: |
| |
| datasource: |
| username: root |
| password: 123456 |
| url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT |
| |
| driver-class-name: com.mysql.cj.jdbc.Driver |
| |
| |
| @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 |
| |
| # 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; |
| |
| |
| |
| |
| |
| public void set(String key, String value) { |
| redisTemplate.opsForValue().set(key, value); |
| } |
| |
| |
| |
| |
| |
| |
| |
| public void set(String key, String value, long timeout, TimeUnit unit) { |
| redisTemplate.opsForValue().set(key, value, timeout, unit); |
| } |
| |
| |
| |
| |
| |
| public void expire(String key, long time) { |
| redisTemplate.expire(key, time, TimeUnit.SECONDS); |
| } |
| |
| |
| |
| |
| |
| public String get(String key) { |
| return String.valueOf(redisTemplate.opsForValue().get(key)); |
| } |
| |
| |
| |
| |
| |
| public boolean delete(String key) { |
| return redisTemplate.delete(key); |
| } |
| } |
| |
| # 修改获取验证码的接口 |
| @RequestMapping("/code/image") |
| public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException { |
| |
| String code = defaultKaptcha.createText(); |
| logger.info("生成的图形验证码是:" + code); |
| |
| ValueOperations<String, String> operations = redisTemplate.opsForValue(); |
| operations.set(SESSION_KEY , code); |
| |
| BufferedImage image = defaultKaptcha.createImage(code); |
| |
| ServletOutputStream out = response.getOutputStream(); |
| ImageIO.write(image, "jpg", out); |
| } |
| |
| # 修改过滤器中的逻辑 |
| private void validate(HttpServletRequest request) { |
| |
| |
| |
| |
| String inpuCode = request.getParameter("code"); |
| |
| ValueOperations<String, String> operations = redisTemplate.opsForValue(); |
| String redisCode = operations.get(SESSION_KEY);; |
| |
| 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
| |
| |
| |
| <dependency> |
| <groupId>org.springframework.boot</groupId> |
| <artifactId>spring-boot-starter-jdbc</artifactId> |
| </dependency> |
| <dependency> |
| <groupId>mysql</groupId> |
| <artifactId>mysql-connector-java</artifactId> |
| </dependency> |
| |
| |
| spring: |
| |
| datasource: |
| username: root |
| password: 123456 |
| url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT |
| |
| driver-class-name: com.mysql.cj.jdbc.Driver |
| |
| |
| @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 |
| |
| |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术