From 2fbafcdd3e395b56d330d1fdb2bcfcf23ba1bd62 Mon Sep 17 00:00:00 2001 From: click33 <36243476+click33@users.noreply.github.com> Date: Tue, 1 Apr 2025 05:33:10 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9EQA=EF=BC=9A=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E4=BD=8E=E7=89=88=E6=9C=AC=20SpringBoot=20(<2.2.0)=20?= =?UTF-8?q?=E5=BC=95=E5=85=A5=20Sa-Token=20=E6=8A=A5=E9=94=99=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sa-token-demo/pom.xml | 1 + .../pom.xml | 146 ++++++++++++++++++ .../main/java/com/pj/SaTokenApplication.java | 22 +++ .../java/com/pj/current/GlobalException.java | 28 ++++ .../java/com/pj/satoken/SaTokenConfigure.java | 87 +++++++++++ .../java/com/pj/test/LoginController.java | 71 +++++++++ .../src/main/resources/application.yml | 49 ++++++ sa-token-doc/more/common-questions.md | 25 +++ 8 files changed, 429 insertions(+) create mode 100644 sa-token-demo/sa-token-demo-springboot-low-version/pom.xml create mode 100644 sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/SaTokenApplication.java create mode 100644 sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/current/GlobalException.java create mode 100644 sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/satoken/SaTokenConfigure.java create mode 100644 sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/test/LoginController.java create mode 100644 sa-token-demo/sa-token-demo-springboot-low-version/src/main/resources/application.yml diff --git a/sa-token-demo/pom.xml b/sa-token-demo/pom.xml index 26ebcbd4..a9bed331 100644 --- a/sa-token-demo/pom.xml +++ b/sa-token-demo/pom.xml @@ -33,6 +33,7 @@ sa-token-demo-solon-redisson sa-token-demo-springboot sa-token-demo-springboot3-redis + sa-token-demo-springboot-low-version sa-token-demo-springboot-redis sa-token-demo-springboot-redisson sa-token-demo-ssm diff --git a/sa-token-demo/sa-token-demo-springboot-low-version/pom.xml b/sa-token-demo/sa-token-demo-springboot-low-version/pom.xml new file mode 100644 index 00000000..03358c11 --- /dev/null +++ b/sa-token-demo/sa-token-demo-springboot-low-version/pom.xml @@ -0,0 +1,146 @@ + + 4.0.0 + cn.dev33 + sa-token-demo-springboot-low-version + 0.0.1-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-parent + + + + 2.1.18.RELEASE + + + + + + 1.41.0 + com.pj.SaTokenApplication + 1.8 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-aop + + + + + cn.dev33 + sa-token-spring-boot-starter + ${sa-token.version} + + + + cn.hutool + hutool-all + 5.8.36 + + + + + cn.dev33 + sa-token-redis-template + ${sa-token.version} + + + + + org.apache.commons + commons-pool2 + + + + + com.fasterxml.jackson.core + jackson-core + 2.17.3 + + + com.fasterxml.jackson.core + jackson-annotations + 2.17.3 + + + com.fasterxml.jackson.core + jackson-databind + 2.17.3 + + + + + + + + + + + + + + src/main/java + + **/*.xml + + + + src/main/resources + + **/*.* + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + lib/ + ${java.run.main.class} + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + package + + copy-dependencies + + + + ${project.build.directory}/lib + + + + + + + + + \ No newline at end of file diff --git a/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/SaTokenApplication.java b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/SaTokenApplication.java new file mode 100644 index 00000000..a6ddba2e --- /dev/null +++ b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/SaTokenApplication.java @@ -0,0 +1,22 @@ +package com.pj; + +import cn.dev33.satoken.SaManager; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + + +/** + * Sa-Token 测试 + * @author click33 + * + */ +@SpringBootApplication +public class SaTokenApplication { + + public static void main(String[] args) { + SpringApplication.run(SaTokenApplication.class, args); + System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig()); +// System.out.println(StpUtil.getSessionByLoginId(10001)); + } + +} diff --git a/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/current/GlobalException.java b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/current/GlobalException.java new file mode 100644 index 00000000..649bdf06 --- /dev/null +++ b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/current/GlobalException.java @@ -0,0 +1,28 @@ +package com.pj.current; + +import cn.dev33.satoken.util.SaResult; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 全局异常处理 + */ +@RestControllerAdvice +public class GlobalException { + + // 全局异常拦截(拦截项目中的所有异常) + @ExceptionHandler + public SaResult handlerException(Exception e, HttpServletRequest request, HttpServletResponse response) { + + // 打印堆栈,以供调试 + System.out.println("全局异常---------------"); + e.printStackTrace(); + + // 返回给前端 + return SaResult.error(e.getMessage()); + } + +} diff --git a/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/satoken/SaTokenConfigure.java b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/satoken/SaTokenConfigure.java new file mode 100644 index 00000000..2ad7f768 --- /dev/null +++ b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/satoken/SaTokenConfigure.java @@ -0,0 +1,87 @@ +package com.pj.satoken; + +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.filter.SaServletFilter; +import cn.dev33.satoken.interceptor.SaInterceptor; +import cn.dev33.satoken.router.SaHttpMethod; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.util.SaResult; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + + +/** + * [Sa-Token 权限认证] 配置类 + * @author click33 + * + */ +@Configuration +public class SaTokenConfigure implements WebMvcConfigurer { + + /** + * 注册 Sa-Token 拦截器打开注解鉴权功能 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册 Sa-Token 拦截器打开注解鉴权功能 + registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); + } + + /** + * 注册 [Sa-Token 全局过滤器] + */ + @Bean + public SaServletFilter getSaServletFilter() { + return new SaServletFilter() + + // 指定 [拦截路由] 与 [放行路由] + .addInclude("/**")// .addExclude("/favicon.ico") + + // 认证函数: 每次请求执行 + .setAuth(obj -> { + // 输出 API 请求日志,方便调试代码 + // SaManager.getLog().debug("----- 请求path={} 提交token={}", SaHolder.getRequest().getRequestPath(), StpUtil.getTokenValue()); + + }) + + // 异常处理函数:每次认证函数发生异常时执行此函数 + .setError(e -> { + System.out.println("---------- sa全局异常 "); + e.printStackTrace(); + return SaResult.error(e.getMessage()); + }) + + // 前置函数:在每次认证函数之前执行 + .setBeforeAuth(obj -> { + // ---------- 设置一些安全响应头 ---------- + SaHolder.getResponse() + // 服务器名称 + .setServer("sa-server") + // 是否可以在iframe显示视图: DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以 + .setHeader("X-Frame-Options", "SAMEORIGIN") + // 是否启用浏览器默认XSS防护: 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时,停止渲染页面 + .setHeader("X-XSS-Protection", "1; mode=block") + // 禁用浏览器内容嗅探 + .setHeader("X-Content-Type-Options", "nosniff") + + // ---------- 设置跨域响应头 ---------- + // 允许指定域访问跨域资源 + .setHeader("Access-Control-Allow-Origin", "*") + // 允许所有请求方式 + .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE") + // 有效时间 + .setHeader("Access-Control-Max-Age", "3600") + // 允许的header参数 + .setHeader("Access-Control-Allow-Headers", "*"); + + // 如果是预检请求,则立即返回到前端 + SaRouter.match(SaHttpMethod.OPTIONS) + .free(r -> System.out.println("--------OPTIONS预检请求,不做处理")) + .back(); + }) + ; + } + +} diff --git a/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/test/LoginController.java new file mode 100644 index 00000000..bf7650ec --- /dev/null +++ b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/java/com/pj/test/LoginController.java @@ -0,0 +1,71 @@ +package com.pj.test; + +import cn.dev33.satoken.session.SaTerminalInfo; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.stp.parameter.SaLoginParameter; +import cn.dev33.satoken.util.SaResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 登录测试 + * @author click33 + * + */ +@RestController +@RequestMapping("/acc/") +public class LoginController { + + // 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456 + @RequestMapping("doLogin") + public SaResult doLogin(String name, String pwd) { + // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对 + if("zhang".equals(name) && "123456".equals(pwd)) { + StpUtil.login(10001); + StpUtil.getTokenSession(); + return SaResult.ok("登录成功"); + } + return SaResult.error("登录失败"); + } + + // 查询登录状态 ---- http://localhost:8081/acc/isLogin + @RequestMapping("isLogin") + public SaResult isLogin() { + return SaResult.ok("是否登录:" + StpUtil.isLogin()); + } + + // 校验登录 ---- http://localhost:8081/acc/checkLogin + @RequestMapping("checkLogin") + public SaResult checkLogin() { + StpUtil.checkLogin(); + return SaResult.ok(); + } + + // 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo + @RequestMapping("tokenInfo") + public SaResult tokenInfo() { + return SaResult.data(StpUtil.getTokenInfo()); + } + + // 查询账号登录设备信息 ---- http://localhost:8081/acc/terminalInfo + @RequestMapping("terminalInfo") + public SaResult terminalInfo() { + System.out.println("账号 10001 登录设备信息:"); + List terminalList = StpUtil.getTerminalListByLoginId(10001); + for (SaTerminalInfo ter : terminalList) { + System.out.println("登录index=" + ter.getIndex() + ", 设备type=" + ter.getDeviceType() + ", token=" + ter.getTokenValue() + ", 登录time=" + ter.getCreateTime()); + } + return SaResult.data(terminalList); + } + + + // 测试注销 ---- http://localhost:8081/acc/logout + @RequestMapping("logout") + public SaResult logout() { + StpUtil.login(10001, SaLoginParameter.create().setIsConcurrent(false)); + return SaResult.ok(); + } + +} diff --git a/sa-token-demo/sa-token-demo-springboot-low-version/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/resources/application.yml new file mode 100644 index 00000000..ac474574 --- /dev/null +++ b/sa-token-demo/sa-token-demo-springboot-low-version/src/main/resources/application.yml @@ -0,0 +1,49 @@ +# 端口 +server: + port: 8081 + +############## Sa-Token 配置 (文档: https://sa-token.cc) ############## +sa-token: + # token 名称 (同时也是 cookie 名称) + token-name: satoken + # token 有效期(单位:秒) 默认30天,-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) + token-style: uuid + # 是否输出操作日志 + is-log: true + +spring: + # redis配置 + redis: + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器地址 + host: 127.0.0.1 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池最大连接数 + max-active: 200 + # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + # 连接池中的最大空闲连接 + max-idle: 10 + # 连接池中的最小空闲连接 + min-idle: 0 + + + + + \ No newline at end of file diff --git a/sa-token-doc/more/common-questions.md b/sa-token-doc/more/common-questions.md index 45c3c4de..050bcb86 100644 --- a/sa-token-doc/more/common-questions.md +++ b/sa-token-doc/more/common-questions.md @@ -565,9 +565,34 @@ public class SaTokenContextByPatternsRequestCondition extends SaTokenContextForS ``` +### Q:过低的 SpringBoot 版本引入 Sa-Token 后报错 +在低于 2.2.0 时 (不包含2.2.0本身) 的 SpringBoot 项目中引入 Sa-Token 后,项目启动时会报错: +``` txt +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cn.dev33.satoken.spring.SaBeanInject': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [cn.dev33.satoken.spring.SaBeanInject]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/jsontype/PolymorphicTypeValidator +``` +这是由于缺少 jackson 相关依赖导致的,可以手动添加以下依赖来解决: + +``` xml + + + com.fasterxml.jackson.core + jackson-core + 2.17.3 + + + com.fasterxml.jackson.core + jackson-annotations + 2.17.3 + + + com.fasterxml.jackson.core + jackson-databind + 2.17.3 + +```