(一)登录认证
说明:因为这里没有连接数据,我模拟两个用户,用户:zhang ,用户:liu,密码 123456 提前做了加密。
1.密码加密接口
- /**
- * 加密
- * @param pwd
- * @return
- */
- @GetMapping("/register")
- public SaResult register(String pwd) {
- // 注册用户
- String hashpw = BCrypt.hashpw(pwd);
- return SaResult.data(hashpw);
- }
2. 模拟数据库用户信息
- /**
- * 模拟数据库用户信息
- *
- * @param name
- * @return
- */
- private LoginUser builderLoginUser(String name) {
- String dbPwd = "$2a$10$roWr2BV2LcMrGFo2ST.vluO4DkwLVt5LhozZGP4OKz3.eh31lAJ6q";
- Set
perms = new HashSet(); - LoginUser loginUser = new LoginUser();
- loginUser.setPwd(dbPwd);
- loginUser.setName(name);
- if ("zhang".equals(name)) {
- perms.add("*.*.*");
- loginUser.setId(10001);
- loginUser.setMenuPermission(perms);
- } else if ("liu".equals(name)){
- perms.add("web:test:user");
- loginUser.setId(10002);
- loginUser.setMenuPermission(perms);
- }
- return loginUser;
- }
3.登录接口
- /**
- * 登录
- *
- * @param name
- * @param pwd
- * @return
- */
- @GetMapping("/doLogin")
- public SaResult doLogin(String name, String pwd) {
- LoginUser loginUser = builderLoginUser(name);
- boolean checkpw = BCrypt.checkpw(pwd, loginUser.getPwd());
- // 第一步:比对前端提交的账号名称、密码
- if (checkpw) {
- // 第二步:根据账号id,进行登录,指定设备类型
- StpUtil.login(loginUser.getId(), DeviceType.PC.getDevice());
- StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
- return SaResult.data(StpUtil.getTokenInfo());
- }
- return SaResult.error("登录失败");
- }
这里为了做简单测试就不做其它等校验。
StpUtil.login(用户ID,设备类型)
#test#result


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

登录认证成功。
(二)权限认证
所谓权限认证,核心逻辑就是判断一个账号是否拥有指定权限:
深入到底层数据中,就是每个账号都会拥有一个权限码集合,框架来校验这个集合中是否包含指定的权限码。
例如:当前账号拥有权限码集合 ["user-add", "user-delete", "user-get"],这时候我来校验权限 "user-update",则其结果就是:验证失败,禁止访问。
1. 自定义SaPermissionImpl 实现StpInterface 接口
- @Component
- public class SaPermissionImpl implements StpInterface {
-
- /**
- * 获取菜单权限列表
- */
- @Override
- public List
getPermissionList(Object loginId, String loginType) { - // 当用户调用权限验证的时候走
- LoginUser loginUser = getLoginUser();
- // 返回当前登录用户拥有的菜单集合
- return new ArrayList<>(loginUser.getMenuPermission());
- }
-
- private LoginUser getLoginUser() {
- return (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
- }
-
-
- /**
- * 获取角色权限列表
- */
- @Override
- public List
getRoleList(Object loginId, String loginType) { - return null;
- }
- }
说明:前面模拟两个用户,zhang ,权限集合["*.*.*"] 表示超级管理员,啥接口都能访问,liu 是普通用户,权限集合["web:test:user"]
新建两个测试接口:
- @SaCheckPermission("web:test:user")
- @GetMapping("/getLoginUser")
- public SaResult getLoginUser() {
- Object loginId = StpUtil.getLoginId();
- System.out.println("接口[getLoginUser]当前用户:" + loginId);
- return SaResult.data(loginId);
- }
-
-
- @SaCheckPermission("web:test:testPerms")
- @GetMapping("/testPerms")
- public SaResult testPerms() {
- Object loginId = StpUtil.getLoginId();
- System.out.println("接口[testPerms]当前用户:" + loginId);
- return SaResult.data(loginId);
- }
可以看到用户liu是没有第二个接口的权限的。
#test#result

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

用户liu没有第二个接口的权限,测试结果成功。
### 这里输出的log其实是做了全局异常的捕获。
#GlobalExceptionHandler
- import cn.dev33.satoken.exception.NotLoginException;
- import cn.dev33.satoken.exception.NotPermissionException;
- import cn.dev33.satoken.util.SaResult;
- import cn.hutool.http.HttpStatus;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.RestControllerAdvice;
-
- import javax.servlet.http.HttpServletRequest;
-
- /**
- * @author yueF_L
- * @version 1.0
- * @date 2022-09-07 11:20
- * 全局异常处理
- */
- @Slf4j
- @RestControllerAdvice
- public class GlobalExceptionHandler {
-
- /**
- * 认证失败
- */
- @ExceptionHandler(NotLoginException.class)
- public SaResult handleNotLoginException(NotLoginException e, HttpServletRequest request) {
- String requestURI = request.getRequestURI();
- log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
- return SaResult.get(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源", null);
- }
-
- /**
- * 权限码异常
- */
- @ExceptionHandler(NotPermissionException.class)
- public SaResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
- String requestURI = request.getRequestURI();
- log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
- return SaResult.get(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权",null);
- }
-
- }