@Testpublic void testBCryptPasswordEncoder() {BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();String encode = passwordEncoder.encode("1234");String encode2 = passwordEncoder.encode("123456");boolean matches = passwordEncoder.matches("1234", "$2a$10$WCD7xp6lxrS.PvGmL86nhuFHMKJTc58Sh0dG1EQw0zSHjlLFyFvde");System.out.println(encode);System.out.println(encode2);System.out.println(matches);}

文章插图
3.2.3、小疑问解决问题所在:在编写这一块内容的时候其实是有一个疑问在脑子里面的,因为这里的方法是根据用户名来进行查询的,且只有一个方法,那么 如果用户名重复了该怎么办呢,这可是会抛异常的 。
问题思考结果:在查询了许多前辈们的博文之后,虽然没有找到很明确的答案,但是根据这些博文结合自己的思考得出了以下理解 。即 loadUserByUsername方法 中的用户名只是Spring Security的一个叫法,这其实就是 用户的账号 ,框架认为大家的账号都是叫做 username 而已,大家的账号总不能是相同的对吧,有些系统用的是手机号、有些系统用的是ID、有些系统用的是某些特殊标识,我们只需要在方法内部的查询操作中对应上就行, 并不是 强制要求我们必须要有 username 这一字段或必须账号就是 username 。
当然这只是一些 个人理解 ,如果有哪里出入,还请各位指出 。
3.3、自定义登录接口在上一步测试的时候我们能够很明显的感受到Spring Security给我们自带了一个出厂登录接口,但是它一定是符合我们需求的接口吗?所以我们就需要自定义一个自己的登录接口 。
3.3.1、编写登录接口 。编写controller,定义登录接口 。
@RestController@RequestMapping("/user")@Slf4jpublic class UserController {@Autowiredprivate UserService loginService;@PostMapping("/login")public Result<Map<String, String>> login(@RequestBody User user){log.info("登录的用户为{}", user);return loginService.login(user);}}3.3.2、编写登录具体逻辑 。1、这一部分主要是在service层中去实现,这里的话主要是有以下几个步骤 。- UserService中先定义好方法;
- 获取认证入口 AuthenticationManager ;因为Spring Security中并没有将 AuthenticationManager 加入到容器中,所以我们需要手动将其加到Spring容器中再进行注入 。
- 通过 AuthenticationManager 的 authenticate 方法来进行用户认证;authenticate 方法需要传递一个 Authentication 类型的参数,而该类型是一个 接口 ,因此使用该接口的实现类 UsernamePasswordAuthenticationToken 对用户登录信息进行 封装 。
- 判断是否验证成功决定是否抛异常
- 在认证信息 authenticate 中获取登录成功后的用户信息;通过debug调试我们会发现获取的用户信息都存放在 authenticate 的 Principal 中,因此我们只需要获取该属性然后进行强转,就可以获得需要的用户数据了 。
- 使用 userId 生成token;
- userId 用作 key ,将用户信息存入redis;
- 把token响应给前端,我这里使用到了 Map 。
@Servicepublic class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {/** 获取认证入口 */@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate RedisCache redisCache;@Overridepublic Result<Map<String, String>> login(User user) {// 在没认证之前principal, credentials两个参数分别存放用户名和密码UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());// 通过AuthenticationManager的authenticate方法来进行用户认证Authentication authenticate = authenticationManager.authenticate(authenticationToken);// 判断是否验证成功if(Objects.isNull(authenticate)){throw new RuntimeException("用户名或密码错误");}// 在认证信息authenticate中获取登录成功后的用户信息LoginUser loginUser = (LoginUser) authenticate.getPrincipal();// 使用userid生成tokenString userId = loginUser.getUser().getId().toString();String jwt = JwtUtil.createJWT(userId);// userId用作key,将用户信息存入redis,并设置30分钟过期redisCache.setCacheObject("login:" + userId, loginUser, 30, TimeUnit.MINUTES);// 把token响应给前端HashMap<String,String> map = new HashMap<>();map.put("token",jwt);return Result.success(map, "登录成功");}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SpringBoot集成MyBatis的相关要点
- 一文搞懂响应式编程
- SpringBoot 整合 Elasticsearch 实现海量级数据搜索
- SpringBoot接口 - 如何生成接口文档之Swagger技术栈?
- windows基于nginx部署Spring-boot+vue前后端分离项目
- Notifier 一文搞懂Linux内核通知链
- SpringBoot 各种 Web 容器服开启 AccessLog 日志
- 初识SpringBoot Starter
- 月亮|年度最大“超级月亮”来了!摄影师晒小米12S Ultra实拍:环形山清晰可见
- 艺术品|和田玉最主要的分清点,搞懂什么是商品,什么是可观赏的艺术品
