赞
踩
Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证
、权限认证
、Session会话
、单点登录
、OAuth2.0
、微服务网关鉴权
等一系列权限相关问题,简化了相对Shiro或者SpringSecurity的复杂的前置配置,比如自定义的Realm或者全局过滤器这些。
SaToekn与Shiro以及SpringSecurity对比
相同点:都具备认证、授权、加密、会话、缓存、rememerMe等功能,都是一种安全认证框架。
SpringSecurity优点:
Shiro优点:
saToken的优点
StpUtil.login(10001); // 标记当前会话登录的账号id
StpUtil.getLoginId(); // 获取当前会话登录的账号id
StpUtil.isLogin(); // 获取当前会话是否已经登录, 返回true或false
StpUtil.logout(); // 当前会话注销登录
StpUtil.kickout(10001); // 将账号为10001的会话踢下线
StpUtil.hasRole("super-admin"); // 查询当前账号是否含有指定角色标识, 返回true或false
StpUtil.hasPermission("user:add"); // 查询当前账号是否含有指定权限, 返回true或false
StpUtil.getTokenValueByLoginId(10001); // 获取账号id为10001的token令牌值
StpUtil.login(10001, "PC"); // 指定设备标识登录,常用于“同端互斥登录”
StpUtil.kickout(10001, "PC"); // 指定账号指定设备标识踢下线 (不同端不受影响)
StpUtil.openSafe(120); // 在当前会话开启二级认证,有效期为120秒
StpUtil.checkSafe(); // 校验当前会话是否处于二级认证有效期内,校验失败会抛出异常
1.创建SpringBoot项目
2.添加依赖
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.29.0</version>
</dependency>
3.编写配置文件
server: # 端口 port: 8081 # Sa-Token配置 sa-token: # token名称 token-name: token # token有效期,单位s 默认30天, -1代表永不过期 timeout: 2592000 # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) is-concurrent: false # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) is-share: false # token风格 token-style: uuid # 是否输出操作日志 is-log: true
3.启动SpringBoot项目 进行启动
4.编写测试
@Api(tags = "用户基础操作") @RestController @RequestMapping("/acc/") public class LoginController { public static final String LJX = "ljx"; public static final String PASSWORD = "123456"; @GetMapping("doLogin") @ApiOperation("登录操作") public SaResult doLogin(String name, String pwd) { //todo 这个地方放置具体的数据库操作 if (LJX.equals(name) && PASSWORD.equals(pwd)) { // 存放的是登录用户的账户account StpUtil.login(10001); String tokenName = StpUtil.getTokenName(); System.out.println("token名称是"+tokenName); String tokenValue = StpUtil.getTokenValue(); System.out.println("token的值"+tokenValue); SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); System.out.println("token的信息参数"+tokenInfo); return SaResult.ok("登录成功"); } return SaResult.error("登录失败"); } @ApiOperation("判断当前的登录状态") @GetMapping("isLogin") public SaResult isLogin() { return SaResult.ok(StpUtil.isLogin() + ""); } @RequestMapping("tokenInfo") @GetMapping("获取当前的token信息") public SaResult tokenInfo() { return SaResult.data(StpUtil.getTokenInfo()); } @ApiOperation("账号注销登录") @GetMapping("logout") public SaResult logout() { StpUtil.logout(); return SaResult.ok(); } }
1.编写实现StpInterface接口的类 实现获取当前登录用户的权限集合以及角色集合的操作
@Component public class StpInterfaceImpl implements StpInterface { /** * 返回一个账号所拥有的权限码集合 */ @Override public List<String> getPermissionList(Object loginId, String loginType) { // todo 根据从数据库中进行查询 List<String> list = new ArrayList<String>(); 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 loginType) { // todo 根据从数据库中进行查询 List<String> list = new ArrayList<String>(); list.add("admin"); list.add("super-admin"); return list; } }
2.定义全局异常拦截
/** * 全局异常处理 */ @ControllerAdvice public class GlobalException { // 全局异常拦截(拦截项目中的所有异常) @ResponseBody @ExceptionHandler public AjaxJson handlerException(Exception e, HttpServletRequest request, HttpServletResponse response) throws Exception { // 不同异常返回不同状态码 AjaxJson aj; if (e instanceof NotLoginException) { // 如果是未登录异常 NotLoginException ee = (NotLoginException) e; aj = AjaxJson.getNotLogin().setMsg(ee.getMessage()); } else if (e instanceof NotRoleException) { // 如果是角色异常 NotRoleException ee = (NotRoleException) e; aj = AjaxJson.getNotJur("无此角色:" + ee.getRole()); } else if (e instanceof NotPermissionException) { // 如果是权限异常 NotPermissionException ee = (NotPermissionException) e; aj = AjaxJson.getNotJur("无此权限:" + ee.getCode()); } else if (e instanceof DisableLoginException) { // 如果是被封禁异常 DisableLoginException ee = (DisableLoginException) e; aj = AjaxJson.getNotJur("账号被封禁:" + ee.getDisableTime() + "秒后解封"); } else { // 普通异常, 输出:500 + 异常信息 aj = AjaxJson.getError(e.getMessage()); } // 返回给前端 return aj; } }
3.使用鉴权式注解
@Api(tags = "注解鉴权测试") @RestController @RequestMapping("/at/") public class AtController { @SaCheckLogin @ApiOperation("检验之后登录的用户才可以进行操作") @GetMapping("checkLogin") public SaResult checkLogin() { return SaResult.ok(); } @ApiOperation("具有指定权限操作") @SaCheckPermission("user-add") @GetMapping("checkPermission") public SaResult checkPermission() { return SaResult.ok(); } @ApiOperation("同时具有指定权限操作") @SaCheckPermission({"user-add", "user-delete", "user-update"}) @GetMapping("checkPermissionAnd") public SaResult checkPermissionAnd() { return SaResult.ok(); } @ApiOperation("具有多个指定权限中的一个操作") @SaCheckPermission(value = {"user-add", "user-delete", "user-update"}, mode = SaMode.OR) @GetMapping("checkPermissionOr") public SaResult checkPermissionOr() { return SaResult.ok(); } @ApiOperation("具有指定角色才可以进行操作") @SaCheckRole("admin") @GetMapping("checkRole") public SaResult checkRole() { return SaResult.ok(); } @ApiOperation("开启二级认证") @GetMapping("openSafe") public SaResult openSafe() { // todo 在这个地方添加校验是否开启二级认证 // 打开二级认证,有效期为200秒 StpUtil.openSafe(200); return SaResult.ok(); } @ApiOperation("通过二级认证之后才可以进行操作") @SaCheckSafe @GetMapping("checkSafe") public SaResult checkSafe() { // todo 添加一些需要二级认证之后才可以进行的操作 return SaResult.ok(); } }
@Configuration public class SaTokenConfigure implements WebMvcConfigurer { /** * 注册Sa-Token 的拦截器,打开注解式鉴权功能 */ @Override public void addInterceptors(InterceptorRegistry registry) { // todo 注册注解拦截器 可以用来存放允许放行的路径 // 除了/user/doLogin 可以放行 其余的操作都需要进行登录之后才可以进行操作 registry.addInterceptor(new SaAnnotationInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/user/doLogin"); } @Override // public void addInterceptors(InterceptorRegistry registry) { // // 注册路由拦截器,自定义认证规则 // registry.addInterceptor(new SaRouteInterceptor((req, res, handler)->{ // // 根据路由划分模块,不同模块不同鉴权 // SaRouter.match("/user/**", r -> StpUtil.checkPermission("user")); // SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin")); // SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods")); // SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders")); // SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice")); // SaRouter.match("/comment/**", r -> StpUtil.checkPermission("comment")); // })).addPathPatterns("/**"); // } }
1.自定义token类型
token-style=simple-uuid
2.同端互斥登录 指定客户端登录与退出
StpUtil.login(2345, “PC”);
StpUtil.logout(2345, “PC”);
3.密码加密
SaSecureUtil.md5(“123456”);
SaSecureUtil.md5BySalt(“123456”, “salt”);
4.全局监听器
/** * 自定义侦听器的实现 */ @Component public class MySaTokenListener implements SaTokenListener { /** 每次登录时触发 */ @Override public void doLogin(String loginType, Object loginId, SaLoginModel loginModel) { // ... } /** 每次注销时触发 */ @Override public void doLogout(String loginType, Object loginId, String tokenValue) { // ... } /** 每次被顶下线时触发 */ @Override public void doReplaced(String loginType, Object loginId, String tokenValue) { // ... } ... }
5.与jwt继承
引入依赖
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>1.29.0</version>
</dependency>
配置
sa-token:
# jwt秘钥
jwt-secret-key: 456789123asdfghjk
注入指定Token方式
@Configuration
public class SaTokenConfigure {
// Sa-Token 整合 jwt (Style模式)
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForStyle();
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。