sa-token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等一系列权限相关问题

Related tags

Security java star
Overview

logo

sa-token v1.15.2

这可能是史上功能最全的 Java 权限认证框架!


在线资料

Sa-Token是什么?

sa-token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等一系列权限相关问题

框架针对踢人下线、自动续签、前后台分离、分布式会话……等常见业务进行N多适配,通过sa-token,你可以以一种极简的方式实现系统的权限认证部分

与其它权限认证框架相比,sa-token 具有以下优势:

  1. 简单 :可零配置启动框架,真正的开箱即用,低成本上手
  2. 强大 :目前已集成几十项权限相关特性,涵盖了大部分业务场景的解决方案
  3. 易用 :如丝般顺滑的API调用,大量高级特性统统只需一行代码即可实现
  4. 高扩展 :几乎所有组件都提供了扩展接口,90%以上的逻辑都可以按需重写

有了sa-token,你所有的权限认证问题,都不再是问题!

Sa-Token 能做什么?

  • 登录验证 —— 轻松登录鉴权,并提供五种细分场景值
  • 权限验证 —— 适配RBAC权限模型,不同角色不同授权
  • Session会话 —— 专业的数据缓存中心
  • 踢人下线 —— 将违规用户立刻清退下线
  • 持久层扩展 —— 可集成Redis、Memcached等专业缓存中间件,重启数据不丢失
  • 分布式会话 —— 提供jwt集成和共享数据中心两种分布式会话方案
  • 单点登录 —— 一处登录,处处通行
  • 模拟他人账号 —— 实时操作任意用户状态数据
  • 临时身份切换 —— 将会话身份临时切换为其它账号
  • 无Cookie模式 —— APP、小程序等前后台分离场景
  • 同端互斥登录 —— 像QQ一样手机电脑同时在线,但是两个手机上互斥登录
  • 多账号认证体系 —— 比如一个商城项目的user表和admin表分开鉴权
  • 花式token生成 —— 内置六种token风格,还可自定义token生成策略
  • 注解式鉴权 —— 优雅的将鉴权与业务代码分离
  • 路由拦截式鉴权 —— 根据路由拦截鉴权,可适配restful模式
  • 自动续签 —— 提供两种token过期策略,灵活搭配使用,还可自动续签
  • 会话治理 —— 提供方便灵活的会话查询接口
  • 记住我模式 —— 适配[记住我]模式,重启浏览器免验证
  • 密码加密 —— 提供密码加密模块,可快速MD5、SHA1、SHA256、AES、RSA加密
  • 组件自动注入 —— 零配置与Spring等框架集成
  • 更多功能正在集成中... —— 如有您有好想法或者建议,欢迎加群交流

代码示例

sa-token的API调用非常简单,有多简单呢?以登录验证为例,你只需要:

// 在登录时写入当前会话的账号id
StpUtil.setLoginId(10001);

// 然后在任意需要校验登录处调用以下API
// 如果当前会话未登录,这句代码会抛出 `NotLoginException`异常
StpUtil.checkLogin();

至此,我们已经借助sa-token框架完成登录授权!

此时的你小脑袋可能飘满了问号,就这么简单?自定义Realm呢?全局过滤器呢?我不用写各种配置文件吗?

事实上在此我可以负责的告诉你,在sa-token中,登录授权就是如此的简单,不需要什么全局过滤器,不需要各种乱七八糟的配置!只需要这一行简单的API调用,即可完成会话的登录授权!

当你受够Shiro、Security等框架的三拜九叩之后,你就会明白,相对于这些传统老牌框架,sa-token的API设计是多么的清爽!

权限认证示例 (只有具有user:add权限的会话才可以进入请求)

@SaCheckPermission("user:add")
@RequestMapping("/user/insert")
public String insert(SysUser user) {
	// ... 
	return "用户增加";
}

将某个账号踢下线 (待到对方再次访问系统时会抛出NotLoginException异常)

// 使账号id为10001的会话注销登录
StpUtil.logoutByLoginId(10001);

除了以上的示例,sa-token还可以一行代码完成以下功能:

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 API 众多,请恕此处无法为您逐一展示,更多示例请戳官方在线文档

Star 趋势

Giteye chart

github-chart

参与贡献

众人拾柴火焰高,万丈高楼众人起! sa-token秉承着开放的思想,欢迎大家为框架添砖加瓦:

  1. 核心代码:该部分需要开发者了解整个框架的架构,遵循已有代码规范进行bug修复或提交新功能
  2. 文档部分:需要以清晰明了的语句书写文档,力求简单易读,授人以鱼同时更授人以渔
  3. 社区建设:如果框架帮助到了您,希望您可以加入qq群参与交流,对不熟悉框架的新人进行排难解惑
  4. 框架推广:一个优秀的开源项目不能仅靠闭门造车,它还需要一定的推广方案让更多的人一起参与到项目中
  5. 其它部分:您可以参考项目issues与需求墙进行贡献

作者寄语:参与贡献不光只有提交代码,点一个star、提一个issues都是对开源项目的促进, 如果sa-token帮助到了你,欢迎你把框架推荐给朋友、同事使用,为sa-token的推广做一份贡献

使用sa-token的开源项目

[ sa-plus] 一个基于springboot架构的快速开发框架,内置代码生成器

[ jthink] 一个基于springboot+sa-token+thymeleaf的博客系统

如果您的项目使用了sa-token,欢迎提交pr

友情链接

[ okhttps ] 一个轻量级http通信框架,API设计无比优雅,支持 WebSocket 以及 Stomp 协议

[ 小诺快速开发平台 ] 基于SpringBoot2 + AntDesignVue全新快速开发平台,同时拥有三个版本

交流群

QQ交流群:1002350610 点击加入

微信交流群:

微信群

(扫码添加微信,备注:sa-token,邀您加入群聊)


Comments
  • 路由拦截鉴权 报错 NestedServletException

    路由拦截鉴权 报错 NestedServletException

    使用版本:

    1.30

    报错信息:

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is cn.dev33.satoken.exception.NotLoginException: 未能读取到有效Token

    希望结果:

    不报错

    复现步骤:

    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 的路由拦截器
        registry.addInterceptor(new SaRouteInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/user/register", "/user/login");
      }
    

    类似 https://blog.csdn.net/qq_61317175/article/details/120784746

    opened by iehong 66
  • webflux下,全局过滤器报错:未成功初始化上下文

    webflux下,全局过滤器报错:未成功初始化上下文

    使用版本:

    sa-token-reactor-spring-boot-starter:1.30.0

    测试结果

    标签失效 - @SaCheckLogin 报错代码 - StpUtil.checkLogin()

    Code:

    @Configuration
    public class SaRouterConfig {
    
        @Bean
        public SaReactorFilter getSaReactorFilter() {
            return new SaReactorFilter()
                    .setAuth(obj -> {
                        System.out.println("---------- sa全局认证");
                        SaRouter.match("/api/*/pri/**")
                                .check(r -> StpUtil.checkLogin());
                    });
        }
    
    }
    

    报错信息:

    cn.dev33.satoken.exception.SaTokenException: 未成功初始化上下文
    	at cn.dev33.satoken.context.SaTokenContextForThreadLocalStorage.getBoxNotNull(SaTokenContextForThreadLocalStorage.java:54) ~[sa-token-core-1.30.0.jar:na]
    	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
    Error has been observed at the following site(s):
    	*__checkpoint ⇢ HTTP GET "/api/user/pri/logout" [ExceptionHandlingWebHandler]
    

    希望结果:

    在普通模式下没有问题,webflux模式下follow教程也应该没有问题

    opened by ANUGLYPLUGIN 16
  • StpLogicJwtForMixin下调用StpUtil.login,出现this api is disabled异常?

    StpLogicJwtForMixin下调用StpUtil.login,出现this api is disabled异常?

    使用版本:

    implementation("cn.dev33:sa-token-spring-boot-starter:1.33.0")
    implementation("cn.dev33:sa-token-jwt:1.33.0")
    implementation("cn.dev33:sa-token-dao-redis:1.33.0")
    

    涉及的功能模块:

    sa-token 
    jwt 
    redis 
    StpLogicJwtForMixin
    StpUtil.login(user_id)
    

    测试步骤:

    使用 StpLogicJwtForStateless 正常,一切换成 StpLogicJwtForMixin 就出现一下异常:

    cn.dev33.satoken.exception.ApiDisabledException: this api is disabled
    	at cn.dev33.satoken.jwt.StpLogicJwtForMixin.replaced(StpLogicJwtForMixin.java:149) ~[sa-token-jwt-1.33.0.jar:na]
    	at cn.dev33.satoken.stp.StpLogic.distUsableToken(StpLogic.java:403) ~[sa-token-core-1.33.0.jar:na]
    	at cn.dev33.satoken.stp.StpLogic.createLoginSession(StpLogic.java:362) ~[sa-token-core-1.33.0.jar:na]
    	at cn.dev33.satoken.stp.StpLogic.login(StpLogic.java:331) ~[sa-token-core-1.33.0.jar:na]
    	at cn.dev33.satoken.stp.StpLogic.login(StpLogic.java:293) ~[sa-token-core-1.33.0.jar:na]
    	at cn.dev33.satoken.stp.StpUtil.login(StpUtil.java:135) ~[sa-token-core-1.33.0.jar:na]
    	at com.example.demo.controller.controller.RegisterAndLoginController.sendOrVerify(RegisterAndLoginController.kt:64) ~[main/:na]
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:696) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:779) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
    

    文档里说

    [调用 StpUtil.getExtra("name") 报错:this api is disabled。](https://sa-token.cc/doc.html#/more/common-questions?id=q%ef%bc%9a%e8%b0%83%e7%94%a8-stputilgetextraquotnamequot-%e6%8a%a5%e9%94%99%ef%bc%9athis-api-is-disabled%e3%80%82)
    

    但是我只调用了StpUtil.login这一个函数。

    上面抛出的异常中, 调用StpUtil.login时,内部必然会调用replaced,但是StpLogicJwtForMixinreplaced函数被标记为禁用的throw new ApiDisabledException();

    这是哪里出问题了?

    opened by ddxl123 11
  • webflux 启动加载两次

    webflux 启动加载两次

    使用版本:

    v1.29.0

    报错信息:

    加载了两次

    希望结果:

    只加载一次

    复现步骤:

    引入了sa-token-reactor-spring-boot-starter 和 sa-token-spring-aop启动时报错bean已存在无法注册

    image

    设置spring.main.allow-bean-definition-overriding=true 加载了两次发现加载了两次

    image

    maven依赖: image

    备注:您提供的信息越充足,我们将越能快速的定位错误

    opened by mlmdflr 9
  • 内部服务外网隔离,子服务添加过滤器后报错

    内部服务外网隔离,子服务添加过滤器后报错

    参考文档

    过滤器配置

    @Component
    public class SaTokenConfigure implements WebMvcConfigurer {
    
        @Value("${spring.profiles.active:dev}")
        private String profile;
    
        /**
         * 注册 Sa-Token 全局过滤器
         */
        @Bean
        public SaServletFilter getSaServletFilter() {
            return new SaServletFilter().addInclude("/**").addExclude("/favicon.ico").setAuth(r -> {
    
                // 校验 Id-Token 身份凭证
                if ("prod".equals(profile)) {
                    SaIdUtil.checkCurrentRequestToken();
                }
            }).setError(e -> SaResult.error(e.getMessage()));
        }
    }
    

    异常信息:

    {"code": 500, "msg": "非Web上下文无法获取Request", "data": "null"}
    

    异常位置:

    cn.dev33.satoken.spring.SpringMVCUtil

    /**
     * 获取当前会话的 request 
     * @return request
     */
    public static HttpServletRequest getRequest() {
    	ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    	if(servletRequestAttributes == null) {
    		throw new SaTokenException("非Web上下文无法获取Request");
    	}
    	return servletRequestAttributes.getRequest();
    }
    
    opened by warthur1214 9
  • StpLogicJwtForMixin+jwt+redis,调用注销函数logout()无效

    StpLogicJwtForMixin+jwt+redis,调用注销函数logout()无效

    使用版本:

    implementation("cn.dev33:sa-token-spring-boot-starter:1.33.0")
    implementation("cn.dev33:sa-token-jwt:1.33.0")
    implementation("cn.dev33:sa-token-dao-redis:1.33.0")
    

    涉及的功能模块:

    yml:

      redis:
        host: 127.0.0.1
        port: 6379
        # Redis数据库索引(默认为0)
        database: 0
        # 读取超时时间
        timeout: 30s
        # 连接超时时间
        connect-timeout: 30s
    sa-token:
      # token名称 (同时也是cookie名称),会自动从请求头根据 token-name key,获取 value
      token-name: token
      # token value 的前缀
      token-prefix: Bearer
      # token有效期,单位s 默认30天, -1代表永不过期
      timeout: -1
      # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
      activity-timeout: -1
      # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
      is-concurrent: true
      # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
      is-share: true
      # token风格
      token-style: uuid
      # 是否输出操作日志
      is-log: true
      # jwt 密钥
      jwt-secret-key: longjwtsecretkey1111
    
    sa-token 
    jwt 
    redis 
    StpLogicJwtForMixin
    StpUtil.login(user_id)
    StpUtil.logout()
    

    测试步骤:

    postman

    1. StpUtil.login(user_id) 进行登录。
    2. postman 加上请求头:token: Bearer xxxx.xxx.xxx,请求注销当前会话。
            StpUtil.checkLogin() // 通过。
            StpUtil.logout() 
            StpUtil.checkLogin() // 仍然通过。
    

    为什么logout注销了,还是检测到已登录?并且,redistoken并没有被清除。 再就,手动把redistoken删除,StpUtil.checkLogin() 仍然不会抛出未登录异常。

    看了源码:

    StpLogicJwtForMixin中,logout()没有被标记 [禁用], 但是 logout(Object loginId, String device) 却被标记为 [禁用]。 在 logout() 源码中的注释有一行 // ...,这就令人好奇了,其他地方都没有这样子的注释,就这个函数带有这个注释, 不知道是我使用问题,还是 logout() 没有完善问题... IDEA debug模式调试了下,发现StpLogicJwtForMixinlogout()函数内部的一系列调用,并没有任何涉及Redis相关内容, 好像logout()源码里并不存在对redis进行清除或修改的操作。

    StpLogicJwtForMixin 源码

    	/**
    	 * 会话注销 
    	 */
    	@Override
    	public void logout() {
    		// ... 
    
     		// 从当前 [storage存储器] 里删除 
     		SaHolder.getStorage().delete(splicingKeyJustCreatedSave());
     		
     		// 如果打开了Cookie模式,则把cookie清除掉 
     		if(getConfig().getIsReadCookie()){
     			SaHolder.getResponse().deleteCookie(getTokenName());
    		}
    	}
    

    这有两个相似问题,但是没有结果:#277 #188

    opened by ddxl123 8
  • 版本号统一管理

    版本号统一管理

    本次PR主要针对框架子模块的版本号进行了统一的管理 修改前面临的问题:框架版本升级需要修改所有的子模块pom文件,全局替换或者一个个手动修改容易出问题 由于项目的子模块较多,所有子模块版本号应该统一依赖于父模块的版本号 后续框架版本升级,只需修改父模块pom中的revision属性即可 image image

    本次提交只做了初步的版本号管理优化,最理想的状态应该再新建一个 sa-token-dependencies (版本号管理方案参考 spring-boot 官方项目) 用来统一管理所有引入的依赖,所有子模块引入的引来都不需要定义版本号,由这个dependencies模块来统一管理整个框架的版本号

    opened by ruansheng8 7
  • 错误信息想通过 RestControllerAdvice 进行拦截,拦截到后还是会进行错误内容打印.

    错误信息想通过 RestControllerAdvice 进行拦截,拦截到后还是会进行错误内容打印.

    使用版本:

    1.29.0

    报错信息:

    Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is cn.dev33.satoken.exception.NotLoginException: 未提供Token] with root cause

    希望结果:

    希望通过 RestControllerAdvice 进行获取而不进行这个错误的展示.

    复现步骤:

    全局拦截后任意访问网址.

    image
    opened by PeixyJ 7
  • 目前不支持kotlin spring boot使用是吗?

    目前不支持kotlin spring boot使用是吗?

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cn.dev33.satoken.spring.SaBeanInject': Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [cn.dev33.satoken.spring.SaBeanInject] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@1f89ab83] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:289) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1284) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1201) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.9.jar:5.3.9] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.9.jar:5.3.9] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.4.jar:2.5.4] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.4.jar:2.5.4] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.4.jar:2.5.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.4.jar:2.5.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.4.jar:2.5.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.4.jar:2.5.4] at com.example.kttest.KtTestApplicationKt.main(KtTestApplication.kt:17) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.5.4.jar:2.5.4] Caused by: java.lang.IllegalStateException: Failed to introspect Class [cn.dev33.satoken.spring.SaBeanInject] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@1f89ab83] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:481) ~[spring-core-5.3.9.jar:5.3.9] at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:321) ~[spring-core-5.3.9.jar:5.3.9] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:267) ~[spring-beans-5.3.9.jar:5.3.9] ... 23 common frames omitted Caused by: java.lang.NoClassDefFoundError: cn/dev33/satoken/sso/SaSsoTemplate at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na] at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3166) ~[na:na] at java.base/java.lang.Class.getDeclaredMethods(Class.java:2309) ~[na:na] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463) ~[spring-core-5.3.9.jar:5.3.9] ... 25 common frames omitted Caused by: java.lang.ClassNotFoundException: cn.dev33.satoken.sso.SaSsoTemplate at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) ~[na:na] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) ~[na:na] ... 29 common frames omitted 零配置下出现了这种问题

    opened by MrCh1ppy 7
  • gateway webflux 装饰器模式下提示未成功初始化上下文

    gateway webflux 装饰器模式下提示未成功初始化上下文

    error 参考图例 伪代码 @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); Long requestStartTime = System.currentTimeMillis(); ServerRequest serverRequest = ServerRequest.create(exchange, codecConfigurer.getReaders()); Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> Mono.just(body)); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class); HttpHeaders headers = new HttpHeaders(); headers.putAll(request.getHeaders()); CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); // 写入全局上下文 (同步) SaReactorSyncHolder.setContent(exchange); return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { return chain.filter(exchange.mutate().request(new ServerHttpRequestDecorator(exchange.getRequest()) { @Override public Flux getBody() { return outputMessage.getBody(); }

                    @Override
                    public HttpHeaders getHeaders() {
                        return super.getHeaders();
                    }
                }).response(new ServerHttpResponseDecorator(exchange.getResponse()){
                    @Override
                    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                        //异常代码
                        StpUtil.getTokenInfo();
                        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                            //异常代码
                            StpUtil.getTokenInfo();
                            DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                            DataBuffer join = dataBufferFactory.join(dataBuffers);
                            byte[] content = new byte[join.readableByteCount()];
                            join.read(content);
                            DataBufferUtils.release(join);
                            HttpHeaders headers = getDelegate().getHeaders();
                            headers.putIfAbsent(HttpHeaders.CONTENT_LENGTH, Lists.newArrayList(content.length + ""));
                            return getDelegate().bufferFactory().wrap(content);
                        })).subscriberContext(ctx -> {
                            // 写入全局上下文 (异步)
                            ctx = ctx.put(SaReactorHolder.CONTEXT_KEY, exchange);
                            return ctx;
                        }).doFinally(r -> {
                            // 清除上下文
                            SaReactorSyncHolder.clearContent();
                        });
                    }
                }).build()).subscriberContext(ctx -> {
                    // 写入全局上下文 (异步)
                    ctx = ctx.put(SaReactorHolder.CONTEXT_KEY, exchange);
                    return ctx;
                }).doFinally(r -> {
                    // 清除上下文
                    SaReactorSyncHolder.clearContent();
                });
            }).subscriberContext(ctx -> {
                // 写入全局上下文 (异步)
                ctx = ctx.put(SaReactorHolder.CONTEXT_KEY, exchange);
                return ctx;
            }).doFinally(r -> {
                // 清除上下文
                SaReactorSyncHolder.clearContent();
            }));
    }
    
    opened by llm163520 7
  • iphone登陆后和每call url, 后台都报NotLoginException

    iphone登陆后和每call url, 后台都报NotLoginException

    使用版本:

    1.32

    报错信息:

    thymeleaf + springboot

    用普通电脑登陆后, 然后到处点击url, 后台都不会报NotLoginException 但用iphone的chrome / safari login 后 每call url (controller) 都会报 NotLoginException: 未能读取到有效Token 但frand-end / 页面, 什么事都没有, 后台就是一直报 NotLoginException image

    希望结果:

    iphone登陆后, 理应如电脑登入一般的日志 image

    复现步骤:

    用普通电脑登陆后, 然后到处点击url, 后台都不会报NotLoginException 但用iphone的chrome / safari login 后 每call url (controller) 都会报 NotLoginException: 未能读取到有效Token 但frand-end / 页面, 什么事都没有, 后台就是一直报 NotLoginException

    < 备注:如果复现步骤比较复杂,请将 demo 上传到 gitee 并留下地址 >

    opened by 98549844 6
Releases(v1.33.0)
  • v1.33.0(Nov 16, 2022)

    • 重构:重构异常状态码机制。 [重要]
    • 重构:重构 sa-token-sso 模块异常码改为 300 开头,sa-token-jwt 异常码改为 302 开头。 [不向下兼容]
    • 新增:新增全局 Log 模块。 [重要]
    • 重构:SaTokenListenerForConsolePrint 改名 SaTokenListenerForLog。 [不向下兼容]
    • 修复:修复多线程下 SaFoxUtil.getRandomString() 随机数重复问题。
    • 文档:文档优化。
    Source code(tar.gz)
    Source code(zip)
  • v1.32.0(Oct 28, 2022)

    • 修复:修复 sa-token-dao-redis-fastjson 插件多余序列化 timeout 字段的问题。
    • 修复:修复 sa-token-dao-redis-fastjson 插件 session.getModel 无法反序列化实体类的问题。
    • 修复:修复 sa-token-quick-login 插件指定拦截排除路由不生效的问题。
    • 修复:修复 sa-token-alone-redis + sa-token-dao-redis-fastson 时 Redis 无法分离的问题。
    • 修复:修复在配置了 cookie.path 后,注销时无法彻底清除 Cookie 的问题。
    • 升级:SaFoxUtil.getValueByType() 新增对 char 类型的转换。
    • 新增:新增 sa-token-dao-redis-fastjson2 插件。 [重要]
    • 新增:新增全局配置 is-write-header,控制登录后是否将 Token 写入响应头。 [重要]
    • 新增:二级认证模块新增指定业务标识能力。 [重要]
    • 重构:Id-Token 模块更名为 Same-Token。 [重要] [不向下兼容]
    • 重构:重构会话查询参数作用:由start=-1时查询全部会话,改为 start=0,size=-1 时查询全部。 [不向下兼容]
    • 重构:SaManager.getStpLogic("type") 默认当对应type不存在时不再抛出异常,而是自动创建并返回。
    • 重构:重构SSO模块,静态式API改为实例式:SaSsoHandle -> SaSsoProcessor。 [重要] [不向下兼容]
    • 重构:SSO-Server 端单点注销地址修改 /sso/logout -> /sso/signout,避免与 SSO-Client 端同 path 的冲突。 [不向下兼容]
    • 新增:文档新增 SSO 平台中心模式示例,跳连接进入子系统。 [重要]
    • 新增:新增SSO前后端分离集成示例 vue2 & vue3 版本。 [重要]
    • 重构:SSO 示例项目 http 请求工具改为 Forest。
    • 新增:SSO模块文档新增单个项目同时搭建 sso-serversso-client 的示例。 [重要]
    • 新增:SSO模块文档新增一个项目同时搭建两个 sso-server 服务 的示例。 [重要]
    • 文档:在线文档新增代码示例。
    • 文档:在线文档增加全局调色功能。
    • 文档:[自定义 SaTokenContext 指南] 章节新增对三种模型的解释。
    • 文档:新增多账号体系混合鉴权代码示例。
    • 文档:文档增加 Gradle 依赖方式和 properties 风格配置。
    • 新增:新增 sa-token-dependencies,统一定义依赖版本。 [重要]
    Source code(tar.gz)
    Source code(zip)
  • v1.31.0(Sep 9, 2022)

    • 文档:新增优秀开源案例展示。
    • 文档:新增博客展示,欢迎大家投稿。
    • 新增:新增 SaInterceptor 综合拦截器。 [重要] [不向下兼容]
    • 新增:新增 新增 @SaIgnore 忽略鉴权注解。 [重要]
    • 新增:新增插件 sa-token-dao-redis-fastjson,感谢 @sikadai 提交的pr。 [重要]
    • 新增:新增插件 sa-token-context-grpc,感谢 @LiYiMing666 提交的pr。 [重要]
    • 重构:SaSession 取消 tokenSignList 的 final 修饰符。
    • 新增:SaSession 添加 setTokenSignList 方法。
    • 重构:TokenSign 新增 setValuesetDevice 方法。
    • 修复:修复多账号模式下不能正确重置 StpLogic 的问题。
    • 修复:修复 SaSession 对象中 TokenSign 判断有可能空指针的问题。
    • 修复:解决当权限码为 null 时可能带来的空指针问题。
    • 新增:新增 StpUtil.getExtra(tokenValue, key) 方法,用于获取任意 token 的扩展参数。
    • 优化:优化 StpLogic#logoutByTokenValue 方法逻辑,精简代码。
    • 重构:SaTokenConfig 配置类字段 isReadHead 改为 isReadHeader[不向下兼容]
    • 修复:修复部分场景下踢人下线会抛出异常 非Web上下文无法获取Request 的问题。
    • 新增:新增方法 StpLogic#getAnonTokenSession,可在未登录情况下安全的获取 Token-Session。 [重要]
    • 新增:新增 SaApplication 对象,用于全局作用域存取值。 [重要]
    • 重构:将 SaTokenListener 改为事件发布订阅模式,允许同时注册多个侦听器。 [重要] [不向下兼容]
    • 重构:StpUtil.login(id) 不再强制校验账号是否禁用,需要手动校验。 [不向下兼容]
    • 重构:DisableLoginException 更换名称为 DisableServiceException[不向下兼容]
    • 新增:新增对账号限制、分类封禁、阶梯封禁功能。 [重要]
    • 新增:会话查询API增加反序获取会话方式。
    • 新增:SSO模块增加 server-url 属性,用于简化各种 url 配置。 [重要]
    • 修复:修复单点登录模块 ssoLogoutCall 配置项无效的问题。
    • 优化:优化 SaSsoHandle.checkTicket(ticket, currUri); 方法,使其不提供 currUri 参数时将不再注册单点注销回调。
    • 修复:修复 SaOAuth2Handle 类中 doLogin 方法没有使用 Param.pwd 常量的问题。
    • 新增:新增 SaOAuth2Util.checkClientTokenScope(clientToken, scopes) 方法,校验 Client-Token 是否含有指定 Scope。
    • 删除:删除 sa-token-jwt 模块过期 class。
    • 重构:sa-token-jwt 模块依赖改为 hutool-jwt,并升级版本为 5.8.5。
    • 重构:sa-token-jwt 模块改为 Util + Template 形式,方便针对部分代码重写。 [重要]
    • 新增:在线文档添加API手册。
    • 重构:sa-token-oauth2 模块密码模式新增 client_secret 参数校验。[不向下兼容]
    • 新增:集成 jacoco 插件,核心包单元测试覆盖率提高至 90% 以上。
    • 优化:开源案例分离专属仓库:Awesome-Sa-Token
    Source code(tar.gz)
    Source code(zip)
  • v1.30.0(May 10, 2022)

    • 新增:新增集成 Web-Socket 鉴权示例。 [重要]
    • 新增:新增集成 Web-Socket(Spring封装版) 鉴权示例。
    • 新增:新增 jfinal 集成包 sa-token-jfinal-plugin [重要]
    • 新增:新增 jboot 集成包 sa-token-jboot-plugin (感谢 @nxstv 提交的pr)
    • 修复:修复整合 sa-token-jwt Style 模式时,StpUtil.getExtra("key") 无效的bug
    • 升级:升级 sa-token-context-dubbo dubbo版本:2.7.11 -> 2.7.15
    • 升级:借助 flatten-maven-plugin 统一版本号定义 (感谢 @ruansheng8 提交的pr) [重要]
    • 修复:修复在 springboot 2.6.xquick-login 插件循环依赖无法启动的问题
    • 优化:sa-token-spring-aop 依赖改为 sa-token-core,避免在webflux环境下启动报错的问题
    • 优化:源码注释 设备标识 改为 设备类型 更符合语义
    • 修复:解决部分协议下 dubbo 参数变为小写导致 Id-Token 鉴权无效的问题
    • 升级:单元测试升级为 JUnit5
    • 新增:新增 maxLoginCount 配置,指定同一账号可同时在线的最大数量 [重要]
    • 升级:彻底删除 SaTokenAction 接口,完全由 SaStrategy 代替
    • 新增:新增 sa-token-dao-redisx 插件,感谢 @noear 提交的pr [重要]
    • 优化:增加 parseToken 未配置 jwt 密钥时的异常提示,感谢 @BATTLEHAWK00 提交的pr
    • 优化:sso,oauth2 插件中调用配置类使用 getter 方法,感谢 @Naah 提交的pr
    • 新增:新增 json 转换器模块
    • 重构:SaTokenListener#doLogin 方法新增 tokenValue 参数 [不向下兼容]
    • 升级:SpringBoot 相关组件依赖版本升级至 2.5.12
    • 文档:在线文档所有 AjaxJson 改为 SaResult
    • 文档:“多账号认证” -> 改为 “多账户认证”
    • 文档:部分章节新增动态演示图 [重要]
    • 升级:顶级异常类 SaTokenException 增加 code 异常细分状态码。详见 [重要]
    • 注意升级:受异常细分状态码影响,NotPermissionException 类中 getCode() 方法改为 getPermission() [不向下兼容]
    • SSO 模块升级:
      • 重构:SSO 模块从核心包拆分为独立插件 sa-token-sso [重要]
      • 优化:SSO模式三单点注销回调方法中,注销语句改为:stpLogic.logout(loginId) 更符合情景
      • 修复:解决 sso 构建认证地址时,部分 Servlet 版本内部实现不一致带来的双 back 参数问题。
      • 升级:SSO 模块提供精细化异常处理
      • 重构:SSO 模式三接口 /sso/checkTicket/sso/logout,更改响应体格式 [不向下兼容]
      • 优化:SSO 模式三单点注销搭建示例增加 try-catch,提高容错性
      • 优化:SsoUtil.singleLogout 改为 SsoUtil.ssoLogout,且无需再提供 secretkey 参数 [不向下兼容]
      • 升级:将 SSO 模式三的接口调用改为签名式校验。 [重要] [不向下兼容]
      • 新增:新增 SSO 模式三下无 sdk 的对接示例, 感谢 @Sa-药水 的建议反馈 [重要]
    • sa-token-jwt 模块升级:
      • 重构:sa-token-jwt 的创建,强制校验loginType [不向下兼容]
      • 重构:StpLogicJwtForStateless 由重写 login 方法改为重写 createLoginSession
      • 重构:SaJwtUtil 工具类不再吞并异常消息,且提供精细化异常 code 码。
      • 重构:改名:StpLogicJwtForStyle -> StpLogicJwtForSimple
      • 重构:改名:StpLogicJwtForMix -> StpLogicJwtForMixin
      • 修复:修复 StpLogicJwtForSimple 模式下 Extra 数据可能受到旧 token 影响的bug
    Source code(tar.gz)
    Source code(zip)
  • v1.29.0(Feb 10, 2022)

    • 升级:sa-token-jwt插件可在登录时添加额外数据。
    • 重构:优化Dubbo调用时向下传递Token的规则,可避免在项目启动时由于Context无效引发的bug。
    • 重构:OAuth2 授权模式开放由全局配置和Client单独配置共同设定。
    • 重构:OAuth2 模块部分属性支持每个 Client 单独配置。
    • 重构:OAuth2 模块部分方法名修复单词拼写错误:converXxx -> convertXxx。
    • 重构:修复 OAuth2 模块 deleteAccessTokenIndex 回收 token 不彻底的bug。
    • 新增:OAuth2 模块新增 pastClientTokenTimeout,用于指定 PastClientToken 默认有效期。
    • 文档:常见报错章节增加目录树,方便查阅。
    • 文档:优化文档样式。
    • 新增:新增 BCrypt 加密。
    • 修复:修复StpUtil.getLoginIdByToken(token) 在部分场景下返回出错的bug。
    • 重构:优化OAuth2模块密码式校验步骤。
    • 新增:新增Jackson定制版Session,避免timeout属性的序列化。
    • 新增:SaLoginModel新增setToken方法,用于预定本次登录产生的Token。
    • 新增:新增 StpUtil.createLoginSession() 方法,用于无Token注入的方式创建登录会话。
    • 新增:OAuth2 与 StpUtil 登录会话数据互通。
    • 新增:新增 StpUtil.renewTimeout(100); 方法,用于 Token 的 Timeout 值续期。
    • 修复:修复默认dao实现类中 updateObject 无效的bug
    • 完善:完善单元测试。
    Source code(tar.gz)
    Source code(zip)
  • v1.28.0(Nov 8, 2021)

    • 新增:新增 sa-token-jwt 插件,用于与jwt的整合 [重要]
    • 新增:新增 sa-token-context-dubbo 插件,用于与 Dubbo 的整合 [重要]
    • 文档:文档新增章节:Sa-Token 插件开发指南 [重要]
    • 文档:文档新增章节:名称解释
    • 优化:抽离 getSaTokenDao() 方法,方便重写
    • 新增:单元测试新增多账号模式数据不互通测试
    • 优化:优化在线文档,修复部分错误之处
    • 优化:优化未登录异常抛出提示,标注无效的Token值
    • 修复:修复单词拼写错误 getDeviceOrDefault
    • 优化:优化 jwt 集成示例
    • 文档:新增常见问题总结
    Source code(tar.gz)
    Source code(zip)
  • v1.27.0(Oct 12, 2021)

    • 升级:增强 SaRouter 链式匹配能力 [重要]
    • 新增:新增插件 Thymeleaf 标签方言 [重要]
    • 新增:@SaCheckPermission 增加 orRole 字段,用于权限角色“双重or”匹配 [重要]
    • 升级:Cookie模式增加 securehttpOnlysameSite等属性的配置 [重要]
    • 重构:重构SSO三种模式,抽离出统一的认证中心 [重要]
    • 新增:新增 SaStrategy 策略类,方便内部逻辑按需重写 [重要]
    • 新增:临时认证模块新增 deleteToken 方法用于回收 Token
    • 新增:新增 kickout、replaced 等注销会话的方法,更灵活的控制会话周期 [重要]
    • 新增:权限认证增加API:StpUtil.hasPermissionAndStpUtil.hasPermissionOr
    • 新增:角色认证增加API:StpUtil.hasRoleAndStpUtil.hasRoleOr
    • 新增:新增 StpUtil.getRoleList()StpUtil.getPermissionList() 方法
    • 新增:新增 StpLogic 自动注入特性,可快速方便的扩展 StpLogic 对象
    • 优化:优化同端互斥登录逻辑,如果登录时没有指定设备标识,则默认顶替所有设备下线
    • 优化:在未登录时调用 hasRole 和 hasPermission 不再抛出异常,而是返回false
    • 升级:升级注解鉴权算法,并提供更简单的重写方式
    • 文档:新增常见报错排查,方便快速排查异常报错
    • 文档:文档新增SSO单点登录与OAuth2技术选型对比
    • 破坏式更新:
      • [向下兼容] 废弃 SaTokenAction 接口,替代方案: SaStrategy
      • [向下兼容] 移除 StpUtil.logoutByLoginId() 更换为 StpUtil.kickout();
      • [不向下兼容] 侦听器 doLogoutByLoginId 与 doReplaced 方法移除 device 参数
      • [不向下兼容] 侦听器 doLogoutByLoginId 方法重命名为 doKickout
    Source code(tar.gz)
    Source code(zip)
  • v1.26.0(Sep 2, 2021)

    • 优化:优化单点登录文档
    • 新增:新增 Http Basic 认证 [重要]
    • 新增:文档新增跨域解决方案
    • 文档:新增 Nginx 转发请求丢失uri的解决方案
    • 文档:新增 SSO 自定义 API 路由示例 [重要]
    • 示例:新增 SSO-Server 端前后端分离示例 [重要]
    Source code(tar.gz)
    Source code(zip)
  • v1.25.0(Aug 17, 2021)

    • 新增:SaRequest新增getHeader(name, defaultValue)方法,用于获取header默认值
    • 新增:SaRequest 添加 forward 转发方法
    • 新增:Readme新增源码模块介绍、友情链接、正在使用Sa-Token的项目
    • 重构:重构SSO单点登录模块源码,增加可读性
    • 新增:SSO配置表新增所属端说明
    • 新增:SSO模式三新增账号资料同步示例 [重要]
    • 新增:前后端分离模式下接入SSO的示例 [重要]
    • 优化:优化SSO单点注销重定向逻辑
    • 重构:重构SSO单点登录模块部分API
    • 优化:优化SaQuickBean中过滤器处理逻辑
    • 文档:优化文档样式,增加示例
    • 文档:代码鉴权、注解鉴权、路由拦截鉴权,选择指南
    • 文档:文档新增 SSO旧有系统改造指南
    • 文档:SSO集成文档里添加API列表
    • 文档:新增 Sa-Token-Study 链接,讲解 Sa-Token 源码涉及到的技术点
    • 不兼容更新重构:
      • 重构:修复 SaReactorHolder.getContent() 拼写错误:content -> context
    Source code(tar.gz)
    Source code(zip)
  • v1.24.0(Jul 26, 2021)

    • 修复:修复部分场景下Alone-Redis插件导致项目无法启动的问题
    • 优化:增加对SpringBoot1.x版本的兼容性
    • 新增:SaOAuth2Util新增checkScope函数,用于校验令牌是否具备指定权限
    • 新增:OAuth2.0模块新增revoke接口,用于提前回收 Access-Token 令牌
    • 新增:新增Sa-Id-Token 模块,解决微服务内部调用鉴权 [重要]
    • 文档:新增OAuth2.0模块常用方法说明
    • 优化:大幅度优化文档示例
    Source code(tar.gz)
    Source code(zip)
  • v1.23.0(Jul 19, 2021)

    • 新增:Sa-Token-OAuth2 模块正式发布 [重要]
    • 修复:修复jwt集成demo无法正确注册StpLogic的bug
    • 修复:修复登录时某些场景下Session续期可能不正常的bug
    • 优化:代码注释优化,文档优化
    Source code(tar.gz)
    Source code(zip)
  • v1.22.0(Jul 12, 2021)

    • 新增:SaSsoConfig 部分属性增加set连缀风格
    • 优化:SaSsoUtil 可定制化底层的 StpLogic
    • 新增:新增 SaSsoHandle 大幅度简化单点登录整合步骤 [重要]
    • 新增:新增Sa-Token在线测评,链接:https://ks.wjx.top/vj/wFKPziD.aspx [重要]
    • 新增:Sa-Token-Quick-Login 插件新增拦截与放行路径配置
    • 优化:大幅度优化文档示例
    Source code(tar.gz)
    Source code(zip)
  • v1.21.0(Jul 7, 2021)

    • 新增:新增Token二级认证 [重要]
    • 新增:新增Sa-Token-Alone-Redis独立Redis插件 [重要]
    • 新增:新增SSO三种模式,彻底解决所有场景下的单点登录问题 [重要]
    • 新增:新增多账号模式下,注解合并示例 [重要]
    • 新增:新增SaRouter.back()函数,用于停止匹配返回结果
    • 不兼容更新重构:
      • 更改yml配置前缀:原[spring.sa-token.] 改为 [sa-token.],目前版本暂时向下兼容,请尽快更新
    Source code(tar.gz)
    Source code(zip)
  • v1.20.0(Jun 17, 2021)

    • 新增:新增Solon适配插件,感谢大佬 @刘西东 提供的pr [重要]
    • 新增:新增SaRouter.stop()函数,用于一次性跳出匹配链功能 [重要]
    • 新增:新增单元测试 [重要]
    • 新增:新增临时令牌验证模块 [重要]
    • 新增:新增sa-token-temp-jwt模块整合jwt临时令牌鉴权 [重要]
    • 新增:会话 SaSession.get() 增加缓存API,简化代码
    • 新增:新增框架调查问卷
    • 修复:修复同时引入 Spring Cloud BusSa-Token 冲突的问题 [重要]
    • 修复:修复SaServletFilter异常函数中无法自定义Content-Type的问题
    • 文档:新增微服务依赖引入说明
    • 文档:新增认证流程图
    • 不兼容更新重构:
      • 方法:StpUtil.setLoginId(id) -> StpUtil.login(id)
      • 方法:StpUtil.getLoginKey() -> StpUtil.getLoginType() (注意其它所有地方的LoginKey均已更改为loginType)
      • 工具类:SaRouterUtil -> SaRouter
      • 配置类:allowConcurrentLogin -> isConcurrent
      • 配置类:isV -> isPrint
      • 为保证平滑更新,旧API仍旧保留,但已增加@Deprecated注解,请尽快更新至新API
    Source code(tar.gz)
    Source code(zip)
  • v1.17.0(Apr 17, 2021)

    修复:在WebFlux环境中引入Redis集成包无法启动的问题 修复:修复JWT集成示例中版本升级API的变更 优化:优化启动时字符画打印 文档:新增集成环境说明 文档:新增功能介绍图 新增:全局过滤器增加限定[拦截路径]与[排除路径]功能 重构:全局过滤器执行函数放到成员变量里,连缀风格配置 新增:新增全局侦听器,可在用户登陆、注销、被踢下线等关键性操作时进行一些AOP操作 [重要]

    Source code(tar.gz)
    Source code(zip)
  • v1.16.0(Apr 11, 2021)

    • 新增:新增账号封禁功能,指定时间内账号无法登陆 [重要]
    • 新增:核心包脱离ServletAPI,彻底零依赖! [重要]
    • 新增:新增基于ThreadLocal的上下文容器 [重要]
    • 新增:新增Reactor响应式编程支持,WebFlux集成! [重要]
    • 新增:新增全局过滤器,解决拦截器无法拦截静态资源的问题 [重要]
    • 新增:新增微服务网关鉴权方案!可接入SoulGateway等网关组件! [重要]
    • 新增:AOP切面定义Order顺序为-100,可保证在多个自定义切面前执行
    • 文档:新增推荐公众号列表
    Source code(tar.gz)
    Source code(zip)
  • v1.14.0(Mar 12, 2021)

    • 新增:新增SaLoginModel登录参数Model,适配 [记住我] 模式 [重要]
    • 新增:新增 StpUtil.setLoginId() 时指定token有效期,可灵活控制用户的一次登录免验证时长
    • 新增:新增Cookie时间判断,在timeout设置为-1时,Cookie有效期将为Integer.MAX_VALUE [重要]
    • 新增:新增密码加密工具类,可快速MD5、SHA1、SHA256、AES、RSA加密 [重要]
    • 新增:新增 OAuth2.0 模块 [重要]
    • 新增:SaTokenConfig配置类所有set方法支持链式调用
    • 新增:SaOAuth2Config sa-token oauth2 配置类所有set方法新增支持链式调用
    • 优化:StpLogic类所有getKey方法重名为splicingKey,更语义化的函数名称
    • 新增:IsRunFunction新增noExe函数,用于指定当isRun值为false时执行的函数
    • 新增:SaSession新增数据存取值操作API
    • 优化:优化SaTokenDao接口,增加Object操作API
    • 优化:jwt示例createToken方法去除默认秘钥判断,只在启动项目时打印警告
    • 文档:常见问题新增示例(修改密码后如何立即掉线)
    • 文档:权限认证文档新增[如何把权限精确搭到按钮级]示例说明
    • 文档:优化文档,部分模块添加图片说明
    Source code(tar.gz)
    Source code(zip)
  • v1.13.0(Feb 8, 2021)

    • 优化:优化源码注释与文档
    • 新增:文档集成Gitalk评论系统
    • 优化:源码包Maven版本号更改为变量形式
    • 修复:文档处方法名getPermissionList错误的bug
    • 修复:修复StpUtil.getTokenInfo()会触发自动续签的bug
    • 修复:修复接口 SaTokenDaosearchData 函数注释错误
    • 新增:SaSession的创建抽象到SaTokenAction接口,方便按需重写
    • 新建:框架内异常统一继承 SaTokenException 方便在异常处理时分辨处理
    • 新增:SaSession新增setId()setCreateTime()方法,方便部分框架的序列化
    • 新增:新增autoRenew配置,用于控制是否打开自动续签模式
    • 新增:同域模式下的单点登录 [重要]
    • 新增:完善分布式会话的文档说明
    Source code(tar.gz)
    Source code(zip)
  • v1.12.0(Jan 11, 2021)

    • 新增:提供JWT集成示例 [重要]
    • 新增:新增路由式鉴权,可方便的根据路由匹配鉴权 [重要]
    • 新增:新增身份临时切换功能,可在一个代码段内将会话临时切换为其它账号 [重要]
    • 优化:将SaCheckInterceptor.java更名为SaAnnotationInterceptor.java,更语义化的名称
    • 优化:优化文档
    Source code(tar.gz)
    Source code(zip)
  • v1.11.0(Jan 9, 2021)

  • v1.10.0(Jan 8, 2021)

    • 新增:提供查询所有会话方案 [重要]
    • 修复:修复token设置为永不过期时无法正常被顶下线的bug,感谢github用户 @zjh599245299 提出的bug
    Source code(tar.gz)
    Source code(zip)
  • v1.9.0(Jan 5, 2021)

    • 优化:spring-boot-starter-data-redis 由 2.3.7.RELEASE 改为 2.3.3.RELEASE
    • 修复:补上注解拦截器里漏掉验证@SaCheckRole的bug
    • 新增:新增同端互斥登录,像QQ一样手机电脑同时在线,但是两个手机上互斥登录 [重要]
    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Jan 1, 2021)

    • 优化:优化源码注释
    • 修复:修复部分文档错别字
    • 修复:修复项目文件夹名称错误
    • 优化:优化文档配色,更舒服的代码展示
    • 新增:提供sa-token集成 redisspring-boot-starter 方案 [重要]
    • 新增:新增集成 redis 时,以jackson作为序列化方案 [重要]
    • 新增:dao层默认实现增加定时清理过期数据功能 [重要]
    • 新增:新增token专属session, 更灵活的会话管理 [重要]
    • 新增:增加配置,指定在获取token专属session时是否必须登录
    • 新增:在无token时自动创建会话,完美兼容token-session会话模型! [重要]
    • 修改:权限码限定必须为String类型
    • 优化:注解验证模式由boolean属性改为枚举方式
    • 删除:StpUtil删除部分冗长API,保持API清爽性
    • 新增:新增角色验证 (角色验证与权限验证已完全分离) [重要]
    • 优化:移除StpUtil.kickoutByLoginId()API,由logoutByLoginId代替
    • 升级:开源协议修改为Apache-2.0
    Source code(tar.gz)
    Source code(zip)
  • v1.7.0(Dec 24, 2020)

    • 优化:项目架构改为maven多模块形式,方便增加新模块 [重要]
    • 优化:与springboot的集成改为springboot-starter模式,无需@SaTokenSetup注解即可完成自动装配 [重要]
    • 新增:新增activity-timeout配置,可控制token临时过期与续签功能 [重要]
    • 新增:timeout过期时间新增-1值,代表永不过期
    • 新增:StpUtil.getTokenInfo()改为对象形式,新增部分常用字段
    • 优化:解决在无cookie模式下,不集成redis时会话无法主动过期的问题
    • 修复:修复文档首页样式问题
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(Dec 17, 2020)

    • 新增:花式token生成方案 [重要]
    • 优化:优化readme.md
    • 修复:修复SaCookieOperSaTokenAction无法自动注入的问题
    Source code(tar.gz)
    Source code(zip)
  • v1.5.1(Dec 16, 2020)

    • 新增:细化未登录异常类型,提供五种场景值:未提供token、token无效、token已过期 、token已被顶下线、token已被踢下线 [重要]
    • 修复:修复StpUtil.getSessionByLoginId(String loginId)方法转换key出错的bug,感谢群友 @(#°Д°)、@一米阳光 发现的bug
    • 优化:修改方法StpUtil.getSessionByLoginId(Object loginId)的isCreate值默认为true
    • 修改:方法delSaSession修改为deleteSaSession,更加语义化的函数名称
    • 新增:新增StpUtil.getTokenName()方法,更语义化的获取tokenName
    • 新增:新增SaTokenAction框架行为Bean,方便重写逻辑
    • 优化:Cookie操作改为接口代理模式,使其可以被重写
    • 优化:文档里集成redis部分增加redis的pom依赖示例
    • 修复:登录验证-> StpUtil.getLoginId_defaultNull() 修复方法名错误的问题
    • 优化:优化readme.md
    • 升级:开源协议修改为MIT
    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Dec 16, 2020)

    • 优化:修改一些函数、变量名称,使其更符合阿里java代码规范
    • 优化:tokenValue的读取优先级改为:request > body > header > cookie [重要]
    • 新增:新增isReadCookie配置,决定是否从cookie里读取token信息
    • 优化:如果isReadCookie配置为false,那么在登录时也不会把cookie写入cookie
    • 新增:新增getSessionByLoginId(Object loginId, boolean isCreate)方法
    • 修复:修复文档部分错误,修正群号码
    Source code(tar.gz)
    Source code(zip)
Owner
dromara
poems & dreams
dromara
mall-swarm是一套微服务商城系统,采用了 Spring Cloud Hoxton & Alibaba、Spring Boot 2.3、Oauth2、MyBatis、Docker、Elasticsearch、Kubernetes等核心技术,同时提供了基于Vue的管理后台方便快速搭建系统。mall-swarm在电商业务的基础集成了注册中心、配置中心、监控中心、网关等系统功能。文档齐全,附带全套Spring Cloud教程。

mall-swarm 友情提示 快速体验项目:在线访问地址。 全套学习教程:《mall学习教程》。 Spring Cloud全套教程:《SpringCloud学习教程》。 专属学习路线:学习不走弯路,整理了套非常不错的《mall专属学习路线》。 项目交流:想要加群交流项目的朋友,可以加入mall项目

macro 9.7k Jan 3, 2023
基于SpringCloud2.1的微服务开发脚手架,整合了spring-security-oauth2、nacos、feign、sentinel、springcloud-gateway等。服务治理方面引入elasticsearch、skywalking、springboot-admin、zipkin等,让项目开发快速进入业务开发,而不需过多时间花费在架构搭建上。持续更新中

快速开始 先决条件 首先本机先要安装以下环境,建议先学习了解springboot和springcloud基础知识。 git java8 maven 开发环境搭建 linux和mac下可在项目根目录下执行 ./install.sh 快速搭建开发环境。如要了解具体的步骤,请看如下文档。 具体步骤如下:

zhoutaoo 7.9k Jan 6, 2023
循序渐进,学习Spring Boot、Spring Boot & Shiro、Spring Batch、Spring Cloud、Spring Cloud Alibaba、Spring Security & Spring Security OAuth2,博客Spring系列源码:https://mrbird.cc

Spring 系列教程 该仓库为个人博客https://mrbird.cc中Spring系列源码,包含Spring Boot、Spring Boot & Shiro、Spring Cloud,Spring Boot & Spring Security & Spring Security OAuth2

mrbird 24.8k Jan 6, 2023
:herb: 基于springboot的快速学习示例,整合自己遇到的开源框架,如:rabbitmq(延迟队列)、Kafka、jpa、redies、oauth2、swagger、jsp、docker、spring-batch、异常处理、日志输出、多模块开发、多环境打包、缓存cache、爬虫、jwt、GraphQL、dubbo、zookeeper和Async等等:pushpin:

欢迎大家留言和PR~ Tip: 技术更新换代太快,本仓库仅做参考,自己的项目具体使用哪个版本还需谨慎思考~(不推荐使用最新的版本,推荐使用(最新-1|2)的版本,会比较稳定) spring-boot-quick 前言   自己很早就想搞一个总的仓库就是将自己平时遇到的和学习到的东西整合在一起,方便后

wangxc 2.1k Jan 2, 2023
🚀 The best rbac web framework. base on Spring Boot 2.4、 Spring Cloud 2020、 OAuth2 . Thx Give a star

?? The best rbac web framework. base on Spring Boot 2.4、 Spring Cloud 2020、 OAuth2 . Thx Give a star

pig-mesh 4.3k Jan 8, 2023
Spring boot microservice example with Eureka Server + Eureka Client + Spring Cloud API Gateway + OAuth2.0 + Circuit Breaker + Resilience4J + FeignClient + RestTemplate

Spring boot microservice example Spring boot microservice example with Eureka Server + Eureka Client + Spring Cloud API Gateway + OAuth2.0 + Circuit B

Subhash Lamba 47 Dec 29, 2022
Google Oauth2 login scenario with Spring boot + React

spring-react-google-oauth2 Google Oauth2 login scenario with Spring boot + React Below diagram is based on oauth implicit flow. Result How to start Pr

배진우 14 Nov 24, 2022