一、引入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <dependencies>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency>
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency>
</dependencies>
|
新建一个springboot项目,启动只会打开会有一个springsecurity的登录页面,说明整合成功啦。
二、思路分析
3.1 登录:
自定义登录接口
调用ProviderManager的方法进行认证, 如果认证通过生成 jwt
把用户信息存入redis中
自定义 UserDetailsService
在这实现类中去查询数据库
3.2 校验:
定义 jwt 认证过滤器
获取token’
解析 token 获取其中的 userid
从redis 中获取用户信息
存入 securityContextHolder
三、实现
用户密码加密存储
1 2 3 4 5 6 7 8
| @Test public void TestBCryptPasswordEndoder() { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encode1 = passwordEncoder.encode("1234"); String encode2 = passwordEncoder.encode("1234"); System.out.println(encode1); System.out.println(encode2); }
|
3.1 运行这段测试代码
结果如下,
![](/../images/java/s1.png)
3.2 为什么密码明文一样得到的,但每次调用encode方法的结果确实不一样的?
String encode(CharSequence rawPassword)
:加密原始密码。而BCrypt实现类会随机生成的salt盐来进行加密。
这是因为它在内部运行的时候,会生成一个随机的salt, 前面有一段是相同的字符,它是salt盐跟原文进行一系列的处理再进行操作,所以虽然它的明文是相同的,但是得出来的结果是不同的。
当然,解析这个也行
1 2 3
| BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); System.out.println(passwordEncoder.matches("1234", "$2a$10$WcDdDjvgo8MJiiLjrD1qZ.2DbzsVhQ5bYukkHKKgvitOwCRcZPgae"));
|
结果为: true
登录接口
接下来我们需要自定义登录接口,然后让springsecurity对这个接口放行(不用登录也能访问)。
在接口中我们通过AuthenticationManager的 authenticate 方法来进行用户认证, 所以需要在SecurityConfig中配置把AuthenticationManager主入容器。
认证成功的话要生成一个jwt,放入响应中返回,并且为了让用户下次请求的时候,能通过 jwt 识别出具体哪个用户, 我们需要把用户信息存入redis, 可以把用户id作为key。