• 探索 Sa-Token (二) 登录认证、权限认证


    (一)登录认证

      说明:因为这里没有连接数据,我模拟两个用户,用户:zhang ,用户:liu,密码 123456 提前做了加密。

    1.密码加密接口

    1. /**
    2. * 加密
    3. * @param pwd
    4. * @return
    5. */
    6. @GetMapping("/register")
    7. public SaResult register(String pwd) {
    8. // 注册用户
    9. String hashpw = BCrypt.hashpw(pwd);
    10. return SaResult.data(hashpw);
    11. }

    2. 模拟数据库用户信息

    1. /**
    2. * 模拟数据库用户信息
    3. *
    4. * @param name
    5. * @return
    6. */
    7. private LoginUser builderLoginUser(String name) {
    8. String dbPwd = "$2a$10$roWr2BV2LcMrGFo2ST.vluO4DkwLVt5LhozZGP4OKz3.eh31lAJ6q";
    9. Set perms = new HashSet();
    10. LoginUser loginUser = new LoginUser();
    11. loginUser.setPwd(dbPwd);
    12. loginUser.setName(name);
    13. if ("zhang".equals(name)) {
    14. perms.add("*.*.*");
    15. loginUser.setId(10001);
    16. loginUser.setMenuPermission(perms);
    17. } else if ("liu".equals(name)){
    18. perms.add("web:test:user");
    19. loginUser.setId(10002);
    20. loginUser.setMenuPermission(perms);
    21. }
    22. return loginUser;
    23. }

    3.登录接口

    1. /**
    2. * 登录
    3. *
    4. * @param name
    5. * @param pwd
    6. * @return
    7. */
    8. @GetMapping("/doLogin")
    9. public SaResult doLogin(String name, String pwd) {
    10. LoginUser loginUser = builderLoginUser(name);
    11. boolean checkpw = BCrypt.checkpw(pwd, loginUser.getPwd());
    12. // 第一步:比对前端提交的账号名称、密码
    13. if (checkpw) {
    14. // 第二步:根据账号id,进行登录,指定设备类型
    15. StpUtil.login(loginUser.getId(), DeviceType.PC.getDevice());
    16. StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
    17. return SaResult.data(StpUtil.getTokenInfo());
    18. }
    19. return SaResult.error("登录失败");
    20. }

    这里为了做简单测试就不做其它等校验。

    StpUtil.login(用户ID,设备类型)  

    #test#result

     

     登录成功之后尝试,用token访问下其他接口

     登录认证成功。

    (二)权限认证

    所谓权限认证,核心逻辑就是判断一个账号是否拥有指定权限:

    • 有,就让你通过。
    • 没有?那么禁止访问!

    深入到底层数据中,就是每个账号都会拥有一个权限码集合,框架来校验这个集合中是否包含指定的权限码。

    例如:当前账号拥有权限码集合 ["user-add", "user-delete", "user-get"],这时候我来校验权限 "user-update",则其结果就是:验证失败,禁止访问

    1. 自定义SaPermissionImpl 实现StpInterface 接口

    1. @Component
    2. public class SaPermissionImpl implements StpInterface {
    3. /**
    4. * 获取菜单权限列表
    5. */
    6. @Override
    7. public List getPermissionList(Object loginId, String loginType) {
    8. // 当用户调用权限验证的时候走
    9. LoginUser loginUser = getLoginUser();
    10. // 返回当前登录用户拥有的菜单集合
    11. return new ArrayList<>(loginUser.getMenuPermission());
    12. }
    13. private LoginUser getLoginUser() {
    14. return (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
    15. }
    16. /**
    17. * 获取角色权限列表
    18. */
    19. @Override
    20. public List getRoleList(Object loginId, String loginType) {
    21. return null;
    22. }
    23. }

    说明:前面模拟两个用户,zhang ,权限集合["*.*.*"] 表示超级管理员,啥接口都能访问,liu 是普通用户,权限集合["web:test:user"]

    新建两个测试接口:

    1. @SaCheckPermission("web:test:user")
    2. @GetMapping("/getLoginUser")
    3. public SaResult getLoginUser() {
    4. Object loginId = StpUtil.getLoginId();
    5. System.out.println("接口[getLoginUser]当前用户:" + loginId);
    6. return SaResult.data(loginId);
    7. }
    8. @SaCheckPermission("web:test:testPerms")
    9. @GetMapping("/testPerms")
    10. public SaResult testPerms() {
    11. Object loginId = StpUtil.getLoginId();
    12. System.out.println("接口[testPerms]当前用户:" + loginId);
    13. return SaResult.data(loginId);
    14. }

    可以看到用户liu是没有第二个接口的权限的。

    #test#result

     用户zhang两个接口都这可以正常访问。

     用户liu没有第二个接口的权限,测试结果成功。

    ### 这里输出的log其实是做了全局异常的捕获。

    #GlobalExceptionHandler

    1. import cn.dev33.satoken.exception.NotLoginException;
    2. import cn.dev33.satoken.exception.NotPermissionException;
    3. import cn.dev33.satoken.util.SaResult;
    4. import cn.hutool.http.HttpStatus;
    5. import lombok.extern.slf4j.Slf4j;
    6. import org.springframework.web.bind.annotation.ExceptionHandler;
    7. import org.springframework.web.bind.annotation.RestControllerAdvice;
    8. import javax.servlet.http.HttpServletRequest;
    9. /**
    10. * @author yueF_L
    11. * @version 1.0
    12. * @date 2022-09-07 11:20
    13. * 全局异常处理
    14. */
    15. @Slf4j
    16. @RestControllerAdvice
    17. public class GlobalExceptionHandler {
    18. /**
    19. * 认证失败
    20. */
    21. @ExceptionHandler(NotLoginException.class)
    22. public SaResult handleNotLoginException(NotLoginException e, HttpServletRequest request) {
    23. String requestURI = request.getRequestURI();
    24. log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
    25. return SaResult.get(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源", null);
    26. }
    27. /**
    28. * 权限码异常
    29. */
    30. @ExceptionHandler(NotPermissionException.class)
    31. public SaResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
    32. String requestURI = request.getRequestURI();
    33. log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
    34. return SaResult.get(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权",null);
    35. }
    36. }

  • 相关阅读:
    《 Python List 列表全实例详解系列(九)》__列表反转(6种方法)
    沙盒软件-软件多开-命令行-运行参数-进程通信-运行和评估
    CMakeList整理大全
    Windows系统/Linux系统修改远程连接端口号
    本科生学深度学习-Attention机制
    【C++】spdlog光速入门,C++logger最简单最快的库
    Java中的正则表达式
    “事后达尔文”—— 游戏业务效果评估方法实践
    【SpringBoot】SpringBoot自定义banner,成千上万种可供选择,当然也可以自定义生成哦
    C++多重、多层、分层继承
  • 原文地址:https://blog.csdn.net/weixin_38982591/article/details/126765804