身份认证和权限鉴别,是大多数系统都需要实现的逻辑。从最简单的小型网站的用户登录,到极为庞大复杂的企业级用户权限控制,权限认证可以只是简单的判断查询,也可以是多种权限模型和身份验证方式的复杂混合。
对于 JAVA 生态而言,权限认证早已是老生常谈,如 Shiro、Security 等的传统框架已是必经之路。然而,有没有更为简洁、能写更少代码和配置、更为符合实际业务需求的框架呢?Sa-Token 或许是一个更好的选择。
Sa-Token,是 click33 在 Github 上开源的轻量级 Java 权限认证框架,目前版本为 v1.15.2。
Sa-Token 框架,主要解决的是:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等一系列权限相关问题。框架针对:踢人下线、自动续签、前后台分离、分布式会话等常见业务进行了适配,使开发者可以以一种极简的方式实现系统的权限认证逻辑。
与其他 Java 权限认证框架相比,sa-token 具有以下优势:
要在项目中使用 Sa-Token,可以通过 Maven 引入,在 pom.xml 中加入依赖:
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.15.0.RELEASE</version>
</dependency>
也可以通过 Gradle 引入:
implementation 'cn.dev33:sa-token-spring-boot-starter:1.15.0.RELEASE'
Sa-Token 功能强大,覆盖全面,包括:
Sa-Token 接口简洁,使用方便。如果我们想要实现登录和注销,sa-token 提供了以下方式:
// 标记当前会话登录的账号id
// 建议的参数类型:long | int | String, 不可以传入复杂类型,如:User、Admin等等
StpUtil.setLoginId(Object loginId);
// 当前会话注销登录
StpUtil.logout();
// 获取当前会话是否已经登录,返回true=已登录,false=未登录
StpUtil.isLogin();
// 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.checkLogin()
Sa-Token 还提供了可扩展性极强的权限验证实现。Sa-Token 把【获取当前账号权限码集合】的操作以接口方式暴露,开发者只需实现 StpInterface 接口:
package com.pj.satoken;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.stp.StpInterface;
/**
* 自定义权限验证接口扩展
*/
@Component // 保证此类被SpringBoot扫描,完成sa-token的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一个账号所拥有的权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginKey) {
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
List<String> list = new ArrayList<String>();
list.add("101");
list.add("user-add");
list.add("user-delete");
list.add("user-update");
list.add("user-get");
list.add("article-get");
return list;
}
/**
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
*/
@Override
public List<String> getRoleList(Object loginId, String loginKey) {
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
List<String> list = new ArrayList<String>();
list.add("admin");
list.add("super-admin");
return list;
}
}
然后,我们就可以用以下的 API 来实现鉴权了:
// 当前账号是否含有指定权限, 返回true或false
StpUtil.hasPermission("user:update");
// 当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException
StpUtil.checkPermission("user:update");
// 当前账号是否含有指定权限 [指定多个,必须全部验证通过]
StpUtil.checkPermissionAnd("user:update", "user:delete");
// 当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
StpUtil.checkPermissionOr("user:update", "user:delete");
除此之外,Sa-Token 还有很多“一行式”的代码,可以通过高度抽象的 API 完成复杂的功能:
StpUtil.setLoginId(10001); // 标记当前会话登录的账号id
StpUtil.getLoginId(); // 获取当前会话登录的账号id
StpUtil.isLogin(); // 获取当前会话是否已经登录, 返回true或false
StpUtil.logout(); // 当前会话注销登录
StpUtil.logoutByLoginId(10001); // 让账号为10001的会话注销登录(踢人下线)
StpUtil.hasRole("super-admin"); // 查询当前账号是否含有指定角色标识, 返回true或false
StpUtil.hasPermission("user:add"); // 查询当前账号是否含有指定权限, 返回true或false
StpUtil.getSession(); // 获取当前账号id的Session
StpUtil.getSessionByLoginId(10001); // 获取账号id为10001的Session
StpUtil.getTokenValueByLoginId(10001); // 获取账号id为10001的token令牌值
StpUtil.setLoginId(10001, "PC"); // 指定设备标识登录
StpUtil.logoutByLoginId(10001, "PC"); // 指定设备标识进行强制注销 (不同端不受影响)
StpUtil.switchTo(10044); // 将当前会话身份临时切换为其它账号
Sa-Token 作为一个轻量级 Java 权限认证框架,接口简洁,功能强大,简单易用,可扩展性强,能够适应多种业务场景,无需繁琐的配置文件和和全局过滤器,就能实现复杂和身份认证和权限控制,十分值得尝试使用。