java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot Sa-Token权限认证

SpringBoot整合Sa-Token实现权限认证的示例代码

作者:张老师技术栈

Sa-Token是一个轻量级Java权限认证框架,相比SpringSecurity和Shiro,配置更简单、API更简洁,本文详细介绍了Sa-Token的快速集成、登录认证、权限校验和踢人下等功能,帮助你快速掌握Sa-Token的用技巧,需要的朋友可以参考下

权限认证是每个后台系统都绕不过去的功能。Shiro 配置繁琐、Spring Security 学习曲线陡峭。Sa-Token 是一个轻量级的 Java 权限认证框架,API 设计简洁,几行代码就能集成到 SpringBoot 中。

一、Sa-Token 简介

相比 Spring Security 和 Shiro,Sa-Token 最大的优势就是简单

功能Sa-TokenShiroSpring Security
登录认证StpUtil.login()Subject.login()复杂配置
权限校验@SaCheckPermission配置繁琐@PreAuthorize
踢人下线StpUtil.kickout()需要自己实现需要自己实现
Redis 集成加配置一行要写代码默认支持

核心特点: 零配置、API 简单、内置 Redis 集成、支持 OAuth2。

二、快速集成

1. 引入依赖

<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.37.0</version>
</dependency>

2. 配置(application.yml)

sa-token:
  # token 名称(默认 satoken)
  token-name: token
  # token 有效期(秒,30天)
  timeout: 2592000
  # token 最低活跃频率(秒,-1 不续签)
  active-timeout: -1
  # 是否允许同一账号多地同时登录(true 允许多端登录)
  is-concurrent: true
  # 多人登录时,是否踢掉已登录的(false 不踢)
  is-share: false
  # token 风格
  token-style: uuid
  # 是否输出操作日志
  is-log: true

就这么两配置,不需要别的 XML 或配置类。

三、登录认证

@RestController
@RequestMapping("/auth")
public class AuthController {

    /**
     * 登录接口
     */
    @PostMapping("/login")
    public ResultVO<String> login(@RequestParam String username,
                                   @RequestParam String password) {
        // 校验用户名密码(这里以 admin/123456 为例)
        if (!"admin".equals(username) || !"123456".equals(password)) {
            return ResultVO.error(401, "用户名或密码错误");
        }

        // 执行登录(Sa-Token 自动生成 token)
        StpUtil.login(1001);  // 参数为用户ID

        // 获取 token 返回给前端
        String token = StpUtil.getTokenInfo().getTokenValue();
        return ResultVO.success(token);
    }

    /**
     * 退出登录
     */
    @PostMapping("/logout")
    public ResultVO<?> logout() {
        StpUtil.logout();
        return ResultVO.success("退出成功");
    }

    /**
     * 获取当前登录用户信息
     */
    @GetMapping("/info")
    public ResultVO<?> info() {
        // 获取当前用户ID
        long userId = StpUtil.getLoginIdAsLong();
        return ResultVO.success("当前用户: " + userId);
    }
}

前端请求时在 header 中携带 token:

Authorization: satoken
Content-Type: application/json

四、拦截器配置(需要登录才能访问)

@Configuration
public class SaTokenConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 的路由拦截器
        registry.addInterceptor(new SaInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(
                    "/auth/login",     // 登录接口不拦截
                    "/auth/register",
                    "/doc.html",       // Swagger 文档
                    "/v3/**",
                    "/swagger-ui/**"
                );
    }
}

配置后,所有未登录的请求会返回 401 未登录,不需要自己写拦截器。

五、权限认证

1. 给用户分配权限

@Service
public class UserService {

    /**
     * 获取用户的权限列表(从数据库查询)
     */
    public List<String> getPermissions(Long userId) {
        // 实际项目中从数据库查询
        if (userId == 1001) {
            return Arrays.asList("user.add", "user.delete", "user.update", "user.query");
        }
        return Arrays.asList("user.query");
    }

    /**
     * 获取用户的角色列表
     */
    public List<String> getRoles(Long userId) {
        if (userId == 1001) {
            return Arrays.asList("admin");
        }
        return Arrays.asList("user");
    }
}

2. 注册权限接口

@Component
public class StpInterfaceImpl implements StpInterface {

    @Autowired
    private UserService userService;

    /**
     * 获取用户的权限列表(框架自动调用)
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        Long userId = Long.parseLong(loginId.toString());
        return userService.getPermissions(userId);
    }

    /**
     * 获取用户的角色列表
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        Long userId = Long.parseLong(loginId.toString());
        return userService.getRoles(userId);
    }
}

3. 使用注解控制权限

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/list")
    @SaCheckPermission("user.query")         // 需要 user.query 权限
    public ResultVO<?> list() {
        return ResultVO.success("查询用户列表");
    }

    @PostMapping("/add")
    @SaCheckPermission("user.add")           // 需要 user.add 权限
    public ResultVO<?> add() {
        return ResultVO.success("新增用户");
    }

    @DeleteMapping("/delete")
    @SaCheckPermission("user.delete")        // 需要 user.delete 权限
    public ResultVO<?> delete() {
        return ResultVO.success("删除用户");
    }

    @PutMapping("/update")
    @SaCheckPermission("user.update")        // 需要 user.update 权限
    public ResultVO<?> update() {
        return ResultVO.success("修改用户");
    }
}

4. 角色校验

@GetMapping("/admin/dashboard")
@SaCheckRole("admin")  // 只有 admin 角色能访问
public ResultVO<?> dashboard() {
    return ResultVO.success("管理后台面板");
}

5. 在代码中手动校验

// 校验是否有权限(没有则抛异常)
StpUtil.checkPermission("user.add");

// 校验权限(返回 boolean)
if (StpUtil.hasPermission("user.delete")) {
    // 有权限就执行
}

// 校验角色
StpUtil.checkRole("admin");

六、踢人下线

管理员可以强制让某个用户下线(比如检测到异常登录):

@PostMapping("/kickout")
@SaCheckRole("admin")
public ResultVO<?> kickout(Long userId) {
    // 让指定用户被踢下线
    StpUtil.kickout(userId);
    return ResultVO.success("已强制用户 " + userId + " 下线");
}

被踢的用户下次请求时会收到 401,提示"Token 已被踢下线"。

七、记住我(7天免登录)

// 登录时设置 rememberMe = true,token 有效期自动延长
StpUtil.login(1001, true);
// 不传或 false 则使用配置的 timeout
StpUtil.login(1001);

在配置中设置记住我的时长:

sa-token:
  # 记住我模式的有效期(单位:秒,7天)
  activity-timeout: 604800

八、单点登录(SSO)

Sa-Token 内置了单点登录方案,几行配置就能实现多系统统一登录:

sa-token:
  sso:
    # SSO 认证中心地址
    auth-url: http://sso-server.com:9000/auth
    # 是否开启单点登录
    is-sso: true

详细用法参考 Sa-Token 官方文档(sso 章节)。

九、与你的秒杀系统集成

@RestController
@RequestMapping("/api/seckill")
@SaCheckLogin  // 整个类需要登录才能访问
public class SeckillController {

    @PostMapping("/do/{productId}")
    @SaCheckPermission("seckill.buy")  // 需要秒杀权限
    public ResultVO<?> doSeckill(@PathVariable Long productId) {
        // 获取当前登录用户
        long userId = StpUtil.getLoginIdAsLong();
        return seckillService.doSeckill(productId, userId, "用户" + userId);
    }
}

只用加两个注解,权限控制就搞定了。 比之前可能用的拦截器+Session 方式省事很多。

十、Sa-Token 常用 API 速查

// 登录认证
StpUtil.login(1001);                    // 登录
StpUtil.logout();                       // 登出
StpUtil.getLoginId();                   // 获取当前用户ID
StpUtil.isLogin();                      // 是否登录
StpUtil.checkLogin();                   // 校验登录(未登录抛异常)

// 权限校验
StpUtil.checkPermission("user.add");    // 校验权限
StpUtil.hasPermission("user.add");      // 是否拥有权限
StpUtil.checkRole("admin");             // 校验角色
StpUtil.hasRole("admin");               // 是否拥有角色

// 踢人
StpUtil.kickout(1001);                  // 踢用户下线
StpUtil.logout(1001);                   // 让用户注销(踢下线且清除记录)

// Token 管理
StpUtil.getTokenValue();                // 获取当前 token
StpUtil.getTokenInfo();                 // 获取 token 详细信息

总结: Sa-Token 的核心就两句话——StpUtil.login() 登录,@SaCheckPermission 鉴权。比 Shiro 的 Subject + Realm + 配置文件那一套简洁太多了。

以上就是SpringBoot整合Sa-Token实现权限认证的示例代码的详细内容,更多关于SpringBoot Sa-Token权限认证的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文