SpringBoot整合Sa-Token

SpringBoot整合Sa-Token

    • 入门介绍
    • 技术理论
    • 技术实践

入门介绍

Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等一系列权限相关问题
框架集成简单、开箱即用、API设计清爽,功能十分强大

技术理论

Sa-Token对于权限登录有着更为简洁的API,省下了很多繁琐的固定要写的代码
能做些什么?
登录验证 —— 单端登录、多端登录、同端互斥登录、七天内免登录
权限验证 —— 权限认证、角色认证、会话二级认证
Session会话 —— 全端共享Session、单端独享Session、自定义Session
踢人下线 —— 根据账号id踢人下线、根据Token值踢人下线
账号封禁 —— 指定天数封禁、永久封禁、设定解封时间
持久层扩展 —— 可集成Redis、Memcached等专业缓存中间件,重启数据不丢失
分布式会话 —— 提供jwt集成、共享数据中心两种分布式会话方案
微服务网关鉴权 —— 适配Gateway、Soul、Zuul等常见网关的路由拦截认证
单点登录 —— 内置三种单点登录模式:无论是否跨域、是否共享Redis,都可以搞定
二级认证 —— 在已登录的基础上再次认证,保证安全性
独立Redis —— 将权限缓存与业务缓存分离
临时Token验证 —— 解决短时间的Token授权问题
模拟他人账号 —— 实时操作任意用户状态数据
临时身份切换 —— 将会话身份临时切换为其它账号
前后台分离 —— APP、小程序等不支持Cookie的终端
同端互斥登录 —— 像QQ一样手机电脑同时在线,但是两个手机上互斥登录
多账号认证体系 —— 比如一个商城项目的user表和admin表分开鉴权
花式token生成 —— 内置六种Token风格,还可:自定义Token生成策略、自定义Token前缀
注解式鉴权 —— 优雅的将鉴权与业务代码分离
路由拦截式鉴权 —— 根据路由拦截鉴权,可适配restful模式
自动续签 —— 提供两种Token过期策略,灵活搭配使用,还可自动续签
会话治理 —— 提供方便灵活的会话查询接口
记住我模式 —— 适配[记住我]模式,重启浏览器免验证
密码加密 —— 提供密码加密模块,可快速MD5、SHA1、SHA256、AES、RSA加密
全局侦听器 —— 在用户登陆、注销、被踢下线等关键性操作时进行一些AOP操作
开箱即用 —— 提供SpringMVC、WebFlux等常见web框架starter集成包,真正的开箱即用

技术实践

单点登录
sa-token针对不同情况提供了三种不同的解决方案

前端同域 + 后端同Redis 共享Cookie同步会话
前端不同域 + 后端同Redis URL重定向传播会话
前端不同域 + 后端不同Redis Http请求获取会话

如何选择就是看自己的系统设计了,接下来我会用前端同域后端同redis的方案来实践一下

白话:其实就是单体架构的小Demo,如果你是分布式等设计架构可以参考23模式

创建工程
SpringBoot整合Sa-Token_第1张图片
一些Demo需要的依赖

	<dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintagegroupId>
                    <artifactId>junit-vintage-engineartifactId>
                exclusion>
            exclusions>
        dependency>
        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-lang3artifactId>
            <version>3.9version>
        dependency>
        
        <dependency>
            <groupId>cn.dev33groupId>
            <artifactId>sa-token-spring-boot-starterartifactId>
            <version>1.8.0version>
        dependency>
    dependencies>

一些非必要的Sa-Token配置

# 应用服务 WEB 访问端口
server:
  port: 8080

spring:
  application:
    name: sa-token
  # sa-token配置
  sa-token:
    # token名称 (同时也是cookie名称)
    token-name: satoken
    # token有效期,单位s 默认30天, -1代表永不过期
    timeout: 60
    # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
    activity-timeout: -1
    # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
    allow-concurrent-login: false
    # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
    is-share: false
    # token风格
    token-style: uuid

编写一个随意的Controller和一些随意的接口

package com.demo.satoken.controller;

import cn.dev33.satoken.stp.StpUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

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



    @PostMapping("login")
    public Boolean login(@RequestParam("username") String username,@RequestParam("password") String password){
        if (StringUtils.isBlank(password)) {
            return false;
        }
        RequestAttributes request = RequestContextHolder.getRequestAttributes();
        StpUtil.setLoginId(request.getSessionId());
        return true;
    }

    @GetMapping("isLogin")
    public Boolean isLogin(){
        RequestAttributes request = RequestContextHolder.getRequestAttributes();
        return StpUtil.isLogin();


    }

    @GetMapping("getLoginId")
    public String getLoginId(){
        return StpUtil.getLoginId()+"";
    }

    @GetMapping("logout")
    public String logout(){
        StpUtil.logout();
        return StpUtil.getLoginId()+"";
    }

    @GetMapping("logoutByLoginId")
    public Boolean logoutByLoginId(){
        StpUtil.logoutByLoginId(RequestContextHolder.getRequestAttributes().getSessionId());
        return true;
    }



}

大家可以试着用PostMan或者自己写个极简页面测试一下接口,

一些常用API

StpUtil.login(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.login(10001, "PC");               // 指定设备标识登录
StpUtil.logoutByLoginId(10001, "PC");     // 指定设备标识进行强制注销 (不同端不受影响)
StpUtil.switchTo(10044);                  // 将当前会话身份临时切换为其它账号

一个极简的Demo完成,其实这个框架真的没有什么学习成本,必要时可以去看官方文档,每个功能都可以一行代码搞定,有什么不懂的可以留言私信我!

你可能感兴趣的:(安全框架,java,spring)