市场上,Shiro、SpringSecurity是目前鉴权主要的两个工具组件,在从最基本的配置到约定大于配置的发展道路上,Sa-token 应运而生。
该组件目前在github上仅有1W的star,但是却有着很大的影响力。因为他的简约配置和优雅使用,得到了更多开发者的依赖
1.依赖的引用
<!--权限认证-->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.28.0</version>
</dependency>
2.其基本核心是对 permission 和 role 进行拦截和 判定,所以需要完 成对 StpInterface接口的重写,重写其中两个方法 getPermissionList 和 getRoleList,附上代码:
/**
* Delta Zhang
* 2022-08-16
* 自定义权限验证接口扩展
*/
@Component
public class StpUtilImp implements StpInterface {
@Autowired
private SysRoleMapper sysRoleMapper;
@Autowired
private SysPermissionMapper sysPermissionMapper;
/**
* 不能从StpUtil.getSession() 中去取userID的原因是 数据 库中该用户的权限可实时更改
* @param loginId 登陆者用户ID
* @param loginType
* @return
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
List<SysPermission> list = sysPermissionMapper.selectPermissionsByUserId(String.valueOf(loginId));
return list.stream().map(SysPermission::getName).collect(Collectors.toList());
}
@Override
public List<String> getRoleList(Object loginId, String loginType) {
List<SysRole> list = sysRoleMapper.selectRolesByUserId(String.valueOf(loginId));
return list.stream().map(SysRole::getRoleName).collect(Collectors.toList());
}
}
/**
* Sa-Token相关配置
*/
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
@Autowired
private IgnoreUrlsConfig ignoreUrlsConfig;
/**
* 注册sa-token拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* 路径拦截器 去掉白名单
*/
registry.addInterceptor(new SaRouteInterceptor((req, resp, handler) -> {
// 获取配置文件中的白名单路径
List<String> ignoreUrls = ignoreUrlsConfig.getWhiteUrls();
// 登录认证:除白名单路径外均需要登录认证
SaRouter.match(Collections.singletonList("/**"), ignoreUrls, StpUtil::checkLogin);
})).addPathPatterns("/**");
/**
* 注解拦截器
*/
registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
}
}
4.以上是实现sa-token 的关键几步
5.ignoreUrlsConfig 白名单中配置附
@Component
@Data
@ConfigurationProperties(prefix = "secure.ignored")
public class IgnoreUrlsConfig {
private List<String> whiteUrls = new ArrayList<>();
}
6.当前端发起请求时,后端需要进行登录才能操作,登录的url “/index/login” 我就不附上代码了,主要就是一个
StpUtil.login(userid);
登录之后会在工具类内生成相对应的token 等一系列数据,仅此一步就完成了登录功能
7.如果需要对某个方法进行权限限制 ,如下
@SaCheckLogin
@SaCheckRole(value = {"admin"})
@SaCheckPermission(value = "get:user")
@RequestMapping("/getUser")
public String getUser(){
SysUserDTO sysUser = (SysUserDTO) StpUtil.getSession().get("userInfo");
if (sysUser != null){
return sysUser.toString();
}else {
return "用户未查到!或token失效";
}
}
SaCheckLogin:必须登录才可以进入
SaCheckRole: 必须该角色的才行(上面指的是必须是 admin才可以通过)
SaCheckPermission:必须该权限的才行(上面的权限是获取用户信息)
那么问题来了,SaCheckLogin,SaCheckRole,SaCheckPermission是如何知晓用户信息(角色、权限)的呢?答案当然是在那个StpUtilImp中了,当我们login的时候,会生成基础的用户信息,以及主要的token信息,前端在调用其它接口是,需要带上对应的token,token 会根据封装的信息,调用 getPermissionsList 和 getRolesList 两个方法,以达到权限鉴别的作用
StpUtil 工具类 包含的功能十分完整,登录登出,以及token用户信息,分布式下解决方案等等 等等,感兴趣的小伙伴可以看下官网。