Sa-Token使用介绍

springboot集成Sa-Token

版本

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.3.12.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>cn.dev33</groupId>
        <artifactId>sa-token-spring-boot-starter</artifactId>
        <version>1.28.0</version>
    </dependency>
</dependencies>

登录/登出

  1. StpUtil.login方法会创建一个token,并将token放到cookie中,保存到前端,前端再次访问时会携带此token。StpUtil.isLogin()会根据cookie中的token信息判断用户是否登录。
  2. 通过cookie实现的,不同浏览器,不同终端不能共享登录的token,需要重新登录。
@RestController
@RequestMapping("/user")
public class UserController {


    @RequestMapping("/login")
    public SaResult login(@RequestParam String mobile, @RequestParam String password){
        StpUtil.login(10000);
        return SaResult.ok(StpUtil.getTokenValue());
    }

    @RequestMapping("isLogin")
    public String isLogin() {
        return "当前会话是否登录:" + StpUtil.isLogin();
    }

    @RequestMapping("logout")
    public String logout() {
        StpUtil.logout(10000);
        return "当前会话是否登录:" + StpUtil.isLogin();
    }
    
    @RequestMapping("getPermissionList")
    public SaResult getPermissionList() {
        List<String> permissionList = StpUtil.getPermissionList();
        List<String> roleList = StpUtil.getRoleList();
        permissionList.addAll(roleList);
        return SaResult.data(permissionList);
    }

}

权限验证

  1. 实现StpInterface接口,重写getPermissionList和getRoleList方法,实际业务中可以将用户的权限和角色维护到数据库中。
  2. 程序启动时并不会调用此类的方法,在调用StpUtil.getPermissionList();或者StpUtil.getRoleList();会调用。
@Component    // 保证此类被 SpringBoot 扫描,完成 Sa-Token 的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {

    /**
     * 返回一个账号所拥有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        // 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询权限
        //根据传入的loginId从数据库(或缓存)中查询具体的权限
        List<String> list = new ArrayList<String>();
        list.add("101");
        list.add("user.add");
        list.add("user.update");
        list.add("user.get");
        // list.add("user.delete");
        list.add("art.*");
        return list;
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        // 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询角色
        //根据传入的loginId从数据库(或缓存)中查询具体的权限
        List<String> list = new ArrayList<String>();
        list.add("admin");
        list.add("super-admin");
        return list;
    }

}

获取权限源码分析

#获取用户所有的菜单按钮权限
StpUtil.getPermissionList();

#那么是如何调用我们自定义的StpInterfaceImpl类获取权限的呢?


#StpUtil.getPermissionList()最终调用此方法获取权限
public List<String> getPermissionList(Object loginId) {
   return SaManager.getStpInterface().getPermissionList(loginId, loginType);
}
#SaManager.getStpInterface() 如果stpInterface为空则返回默认的StpInterfaceDefaultImpl对象
#如果不为空则返回stpInterface
public static StpInterface getStpInterface() {
            if (stpInterface == null) {
                    synchronized (SaManager.class) {
                            if (stpInterface == null) {
                                    SaManager.stpInterface = new StpInterfaceDefaultImpl();
                            }
                    }
            }
            return stpInterface;
    }

#那么stpInterface是如何初始化为我们自定义的StpInterfaceImpl的呢?
#项目启动时sa-token-spring-boot-autoconfigure包下cn.dev33.satoken.spring.SaBeanInject会注入我们自定义的类
#@Component  
#public class StpInterfaceImpl implements StpInterface 
/**
 * 注入权限认证Bean
 * 
 * @param stpInterface StpInterface对象 
 */
@Autowired(required = false)
public void setStpInterface(StpInterface stpInterface) {
        SaManager.setStpInterface(stpInterface);
}

#项目启动后SaManager的属性stpInterface已经被初始化为我们的StpInterfaceImpl实例,项目中调用后StpUtil.getPermissionList();后则会调用我们重新的getPermissionList()方法。

下线

强制注销等价于对方主动调用了注销方法,再次访问会提示:Token无效。
踢人下线不会清除Token信息,而是将其打上特定标记,再次访问会提示:Token已被踢下线。

StpUtil.logout(10001);                    // 强制指定账号注销下线 
StpUtil.logout(10001, "PC");              // 强制指定账号指定端注销下线 
StpUtil.logoutByTokenValue("token");      // 强制指定 Token 注销下线 

StpUtil.kickout(10001);                    // 将指定账号踢下线 
StpUtil.kickout(10001, "PC");              // 将指定账号指定端踢下线
StpUtil.kickoutByTokenValue("token");      // 将指定 Token 踢下线

SSO单点登录

前端同域,后端同redis

  1. 客户端前端同域,则cookie可以存在相同的域名或顶级域名下,一个客户端登录成功后,将token信息保存到域名下的cookie中
  2. 其他不同客户端访问时,因为域名或者顶级域名相同,也能取到域名下的cookie中的token信息并传到后端

前端不同域,后端同redis

在这里插入图片描述

  1. 由于前端客户端不同域,那么不同客户端登录后,保存cookie中的token信息其他客户端并不能取到。因此需要一个能够传递token媒介。

  2. 认证信息的service端只有一个域名,因此把认证信息的service端域名下的cookie作为传输的媒介。

  3. 当客户端1登录时,客户端1未登录,则重定向到service端进行登录(携带着客户端自己的地址,等认证通过后跳转回来),sevice端弹出登录界面,输入账号、密码登录完成后,将token信息保存到service域名的cookie下。

  4. service已登录,创建ticket(创建一个key与账号的缓存)信息并携带ticket信息重定向到到客户端1,客户端1根据ticket中的账号信息进行登录,并重定像到最初的地址(保存token信息到客户端1域名下的cookie)。

  5. 客户端2进行登录,客户端2未登录,则重定向到service端进行登录,此时重定像到service端的时候,能够携带sevice端域名下的cookie中的token信息进行验证,验证已登录,则创建ticket(信息并携带ticket信息重定向到到客户端2。

     ***可能大家会想,用户A认证通过SSO后,通过回调地址将Token返回给原业务系统,原业务系统直接设置登
     录状态,这样流程简单,也完成了登录,那为什么还要还要拿Token再次访问SSO进行验证呢?其实这样问题
     时很严重的,如果用户在SSO没有登录,而是直接在浏览器中敲入回调的地址,并带上伪造的用户信息,是不
     是业务系统也认为登录了呢?这是很可怕的。***
    
  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值