• 【用户登录】模块之登录认证+鉴权业务逻辑


    用户登录——⭐认证功能流程图


    ⭐鉴权流程图:


    用户登录功能的Java代码实现

    1. 实体类-User

    orm框架:JPA

    1. @Table(name = "user_tab")
    2. @Entity
    3. @Data
    4. @NoArgsConstructor
    5. @AllArgsConstructor
    6. public class User implements Serializable {
    7. @Id
    8. @GeneratedValue(strategy = GenerationType.IDENTITY)
    9. @Column(name="user_id")
    10. private Long id;
    11. @Column(name="user_name")
    12. private String username;
    13. @Column(name="user_password")
    14. private String password;
    15. @Column(name="user_phone")
    16. private String phone;
    17. @Column(name="user_nickname")
    18. private String nickname;
    19. @Column(name="user_create_by")
    20. private String createBy;
    21. @Column(name="user_create_time")
    22. private Date createTime;
    23. @Column(name="user_update_time")
    24. private Date updateTime;
    25. @Column(name="user_role_id")
    26. private Long roleId;
    27. }

    2. UserDao

    1. @Repository
    2. public interface UserDao extends JpaRepository {
    3. //根据user的username和password查询该用户
    4. User findByUsernameAndPassword(String username,String password);
    5. }

    3. UserService业务层接口

    1. public interface UserService {
    2. //全查询
    3. List findAllUsers();
    4. //1027-【从数据库读取用户名信息存入布隆过滤器中】
    5. void warnUpUsernames();
    6. //1027-【用户登录】
    7. User login(String username, String password);
    8. }

    4. ⭐UserServiceImpl业务实现类

    1. @Service
    2. @Slf4j
    3. public class UserServiceImpl implements UserService {
    4. @Autowired
    5. private UserDao userDao;
    6. @Autowired
    7. private StringRedisTemplate stringRedisTemplate;
    8. //全查询
    9. @Override
    10. public List findAllUsers() {
    11. return userDao.findAll();
    12. }
    13. //1027-【从数据库读取用户名信息存入布隆过滤器中】
    14. @Override
    15. public void warnUpUsernames() {
    16. userDao.findAll().forEach(u -> {
    17. stringRedisTemplate.opsForValue()
    18. .getOperations()
    19. .execute(new DefaultRedisScript(
    20. "return redis.call('bf.add',KEYS[1],ARGV[1])"
    21. , Long.class),
    22. new ArrayList() {{
    23. add("whiteUsernames");
    24. }}, u.getUsername()
    25. );
    26. }
    27. );
    28. }
    29. //1027-【用户登录】
    30. @Override
    31. public User login(String username, String password) {
    32. if(!StringUtils.hasText(username)){
    33. throw new UsernameIsEmptyException("用户名为空异常");
    34. }
    35. username = username.trim();
    36. if(checkFromWhite(username)){
    37. throw new UsernameNotFoundException("用户名不存在异常");
    38. }
    39. User user = userDao.findByUsernameAndPassword(username, password);
    40. if(Objects.isNull(user)){
    41. throw new BadCredentialsException("用户名|密码错误");
    42. }
    43. return user;
    44. }
    45. //判断用户名是否存在于布隆过滤器
    46. private boolean checkFromWhite(String username) {
    47. Long isExist = stringRedisTemplate.opsForValue()
    48. .getOperations()
    49. .execute(new DefaultRedisScript("return redis.call('bf.exists',KEYS[1],ARGV[1])", Long.class),
    50. new ArrayList() {{
    51. add("whiteUsernames");
    52. }}, username);
    53. return isExist.intValue() == 0;
    54. }

    5. ⭐UserController控制层接口

    1. @Api(tags = "用户模块接口")
    2. @RestController
    3. @RequestMapping("/api/user")
    4. @Slf4j
    5. public class UserController {
    6. @Autowired
    7. private UserService userService;
    8. @Autowired
    9. private StringRedisTemplate stringRedisTemplate;
    10. //1027-【全查询】
    11. @ApiOperation(value = "findAllUsers",notes = "查询所有用户,需要当前用户登录状态")
    12. @GetMapping("/findAllUsers")
    13. @BmsRole(value="1")
    14. public HttpResp> findAllUsers(){
    15. return HttpResp.success(userService.findAllUsers());
    16. }
    17. //1027-【用户登录】
    18. @ApiOperation(value = "login",notes = "用户登录")
    19. @GetMapping("login")
    20. public HttpResp login(HttpServletResponse response, String username, String password){
    21. //首先调用AuthorityService的login方法进行用户登录验证,返回一个User对象。
    22. User user = userService.login(username,password);
    23. //然后生成一个JWT作为用户的身份认证凭证,其中包含了用户名和过期时间等信息。
    24. //使用JWT.create()创建JWT对象,并使用withClaim()方法设置用户名,withExpiresAt()方法设置过期时间。
    25. String salt = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8));
    26. log.debug("user:{}",user);
    27. String token = JWT.create()
    28. .withClaim("username", username)
    29. .withClaim("roleId",""+user.getRoleId())
    30. .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 30)) //30分钟令牌过期
    31. .sign(Algorithm.HMAC256(salt)); //使用Algorithm.HMAC256(salt)指定加密算法和密钥,对JWT进行签名。
    32. log.debug("用户验证通过,生成token为:{}",token);
    33. //将生成的JWT存储到Redis缓存中,使用stringRedisTemplate.opsForValue().set()方法设置键值对,并使用stringRedisTemplate.expire()方法设置过期时间
    34. stringRedisTemplate.opsForValue().set(token,salt);
    35. stringRedisTemplate.expire(token,60, TimeUnit.MINUTES); //60分钟redis缓存token过期
    36. response.addCookie(new Cookie("token",token)); //将JWT作为Cookie添加到HTTP响应中,使用response.addCookie()方法
    37. return HttpResp.success(user); //最后返回一个成功的响应,消息体中包含了登录成功的用户对象
    38. }
    39. }

    用户认证解决方案

    1. 配置部署拦截器

    1. @Configuration
    2. @Slf4j
    3. public class BmsMvcConfig implements WebMvcConfigurer {
    4. @Bean
    5. public AuthorityInterceptor authorityInterceptor(){
    6. log.debug("BmsMvc拦截器启动成功:{}..........",new Date());
    7. return new AuthorityInterceptor();
    8. }
    9. @Override
    10. public void addInterceptors(InterceptorRegistry registry) {
    11. registry.addInterceptor(authorityInterceptor())
    12. .addPathPatterns("/api/**")
    13. .excludePathPatterns(
    14. "/api/user/login"
    15. );
    16. }
    17. }

    2. ⭐自定义拦截器

    1. @Slf4j
    2. public class AuthorityInterceptor implements HandlerInterceptor {
    3. @Autowired
    4. private StringRedisTemplate stringRedisTemplate;
    5. /**
    6. *
    7. * @param request
    8. * @param response
    9. * @param handler 当前拦截器拦截的方法
    10. * @return
    11. * @throws Exception
    12. */
    13. @Override
    14. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    15. log.debug("已进入拦截器:{}",new Date());
    16. String token = request.getHeader("token");
    17. //1.从redis中读取token,如果不存在,则用户是非法用户,抛出自定义异常类InvalidTokenException
    18. Boolean isRedis = stringRedisTemplate.hasKey(token);
    19. if(!isRedis) throw new InvalidTokenException("无效的token");
    20. String salt = stringRedisTemplate.opsForValue().get(token);
    21. log.debug("salt:{}",salt);
    22. DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(salt)).build().verify(token);
    23. //2.token验证完成正确
    24. String roleId = decodedJWT.getClaim("roleId").asString();
    25. log.debug("------->roleId:{}",roleId);
    26. HandlerMethod method = (HandlerMethod) handler;
    27. //System.out.println("----->"+method.getMethod().getDeclaredAnnotation(GetMapping.class));
    28. BmsRole bmsRole= method.getMethod().getDeclaredAnnotation(BmsRole.class);
    29. String requiredRolId = bmsRole.value();
    30. if(!roleId.equals(requiredRolId)){
    31. throw new PermissionDeniedException("您没有足够的权限");
    32. }
    33. //获取请求对象的角色名称
    34. //获取请求的地址(uri)
    35. // String requestURI = request.getRequestURI();
    36. // requestURI = requestURI.substring(requestURI.lastIndexOf("/") + 1);
    37. // log.debug("请求路径uri:{}",requestURI);//URL/URI
    38. // System.out.println(handler.getClass());
    39. return HandlerInterceptor.super.preHandle(request, response, handler);
    40. }
    41. }

    3. 在spring.factories文件加载部署

    1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    2. com.****.bms.authority.config.BmsMvcConfig,com.****.bms.authority.handler.UserExceptionHandler

    未完待续......

  • 相关阅读:
    win-redis使用技巧--和问题解决
    数据科学面试你应该知道的10个统计概念
    shiro 框架使用实例
    【Hack The Box】linux练习-- Poison
    springboot12总结篇(9 10 11)
    阿里云ACE认证的含金量高吗?如何通过ACE认证考试?
    (附源码)计算机毕业设计SSM基于的冠状病毒疫情防控资讯交流推荐网站
    恒源云-Pycharm远程训练避坑指南
    MD5加密接口
    JAVA设计模式--创建型模式--单例模式
  • 原文地址:https://blog.csdn.net/m0_62006803/article/details/134093649