From 8efce6198817e7bec23fed3bd02150b430ef980f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=94?= <2393584716@qq.com> Date: Thu, 6 Feb 2020 00:52:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/sa-token-spring-1.0.0.jar | Bin 37151 -> 37188 bytes .../java/com/pj/SaTokenDemoApplication.java | 7 ++ .../java/com/pj/satoken/MySaTokenConfig.java | 29 +++++ .../main/java/com/pj/satoken/StpCustom.java | 3 +- .../main/java/com/pj/test/TestController.java | 23 ++-- .../dev33/satoken/config/SaTokenConfig.java | 4 +- ...sionUtil.java => SaSessionCustomUtil.java} | 4 +- sa-token-doc/doc/.nojekyll | 0 sa-token-doc/doc/README.md | 49 ++++++++ sa-token-doc/doc/_sidebar.md | 31 +++++ sa-token-doc/doc/index.html | 110 ++++++++++++++++++ sa-token-doc/doc/logo.png | Bin 0 -> 4882 bytes sa-token-doc/doc/more/common-questions.md | 18 +++ sa-token-doc/doc/more/link.md | 9 ++ sa-token-doc/doc/more/update-log.md | 7 ++ sa-token-doc/doc/start/download.md | 24 ++++ sa-token-doc/doc/start/example.md | 85 ++++++++++++++ sa-token-doc/doc/use/config.md | 68 +++++++++++ sa-token-doc/doc/use/dao-extend.md | 106 +++++++++++++++++ sa-token-doc/doc/use/jur-auth.md | 75 ++++++++++++ sa-token-doc/doc/use/kick.md | 15 +++ sa-token-doc/doc/use/login-auth.md | 38 ++++++ sa-token-doc/doc/use/many-account.md | 28 +++++ sa-token-doc/doc/use/mock-person.md | 24 ++++ sa-token-doc/doc/use/not-cookie.md | 47 ++++++++ sa-token-doc/doc/use/session.md | 37 ++++++ sa-token-doc/index.css | 60 ++++++++++ sa-token-doc/index.html | 97 ++++++++++++++- 28 files changed, 979 insertions(+), 19 deletions(-) create mode 100644 sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java rename sa-token-dev/src/main/java/cn/dev33/satoken/session/{SaSessionUtil.java => SaSessionCustomUtil.java} (94%) create mode 100644 sa-token-doc/doc/.nojekyll create mode 100644 sa-token-doc/doc/README.md create mode 100644 sa-token-doc/doc/_sidebar.md create mode 100644 sa-token-doc/doc/index.html create mode 100644 sa-token-doc/doc/logo.png create mode 100644 sa-token-doc/doc/more/common-questions.md create mode 100644 sa-token-doc/doc/more/link.md create mode 100644 sa-token-doc/doc/more/update-log.md create mode 100644 sa-token-doc/doc/start/download.md create mode 100644 sa-token-doc/doc/start/example.md create mode 100644 sa-token-doc/doc/use/config.md create mode 100644 sa-token-doc/doc/use/dao-extend.md create mode 100644 sa-token-doc/doc/use/jur-auth.md create mode 100644 sa-token-doc/doc/use/kick.md create mode 100644 sa-token-doc/doc/use/login-auth.md create mode 100644 sa-token-doc/doc/use/many-account.md create mode 100644 sa-token-doc/doc/use/mock-person.md create mode 100644 sa-token-doc/doc/use/not-cookie.md create mode 100644 sa-token-doc/doc/use/session.md create mode 100644 sa-token-doc/index.css diff --git a/sa-token-demo-springboot/lib/sa-token-spring-1.0.0.jar b/sa-token-demo-springboot/lib/sa-token-spring-1.0.0.jar index cce96b09433139309af27f3136f3462bb2e030dd..d93b176e5f6424ce6928a6df36fa67080f99cae7 100644 GIT binary patch delta 3494 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 + System.out.println("启动成功:sa-token配置如下:" + SaTokenManager.getConfig()); } + + + + + } \ No newline at end of file diff --git a/sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java b/sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java new file mode 100644 index 00000000..846eff03 --- /dev/null +++ b/sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java @@ -0,0 +1,29 @@ +//package com.pj.satoken; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.context.annotation.Primary; +// +//import cn.dev33.satoken.config.SaTokenConfig; +// +///** +// * sa-token代码方式进行配置 +// */ +//@Configuration +//public class MySaTokenConfig { +// +// // 获取配置Bean +// @Primary +// @Bean(name="MySaTokenConfig") +// public SaTokenConfig getSaTokenConfig() { +// SaTokenConfig config = new SaTokenConfig(); +// config.setTokenName("satoken"); // token名称(同时也是cookie名称) +// config.setTimeout(30 * 24 * 60 * 60); // token有效期,单位s 默认30天,-1为永不过期 +// config.setIsShare(true); // 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) +// config.setIsReadHead(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取 +// config.setIsReadBody(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取 +// config.setIsV(true); // 是否在初始化配置时打印版本字符画 +// return config; +// } +// +//} diff --git a/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpCustom.java b/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpCustom.java index 6de6ce8f..e53b1fa5 100644 --- a/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpCustom.java +++ b/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpCustom.java @@ -13,9 +13,10 @@ import cn.dev33.satoken.stp.StpInterface; @Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token的自定义权限验证扩展 public class StpCustom implements StpInterface { + // 返回一个账号所拥有的权限码集合 @Override public List getPermissionCodeList(Object login_id, String login_key) { - List list = new ArrayList(); + List list = new ArrayList(); // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限 list.add("101"); list.add("user-add"); list.add("user-delete"); diff --git a/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java b/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java index fd63fe4a..064c60d4 100644 --- a/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java +++ b/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java @@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import cn.dev33.satoken.session.SaSessionUtil; +import cn.dev33.satoken.session.SaSessionCustomUtil; import cn.dev33.satoken.stp.StpUtil; @RestController @@ -22,9 +22,16 @@ public class TestController { System.out.println("登录成功"); System.out.println("当前是否登录:" + StpUtil.isLogin()); System.out.println("当前登录账号:" + StpUtil.getLoginId()); - System.out.println("当前登录账号:" + StpUtil.getLoginId_asInt()); // 获取登录id并转为int - + System.out.println("当前登录账号:" + StpUtil.getLoginId_asInt()); // 获取登录id并转为int + +// StpUtil.logout(); +// System.out.println("注销登录"); +// System.out.println("当前是否登录:" + StpUtil.isLogin()); +// System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull()); +// StpUtil.setLoginId(id); // 在当前会话登录此账号 + System.out.println("当前token信息:" + StpUtil.getTokenInfo()); // 获取登录id并转为int + System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull()); return AjaxJson.getSuccess(); } @@ -70,11 +77,11 @@ public class TestController { public AjaxJson session2() { System.out.println("======================= 进入方法,测试自定义session接口 ========================= "); // 自定义session就是无需登录也可以使用 的session :比如拿用户的手机号当做 key, 来获取 session - System.out.println("自定义 session的id为:" + SaSessionUtil.getSessionById("1895544896").getId()); - System.out.println("测试取值name:" + SaSessionUtil.getSessionById("1895544896").getAttribute("name")); - SaSessionUtil.getSessionById("1895544896").setAttribute("name", "张三"); // 写入值 - System.out.println("测试取值name:" + SaSessionUtil.getSessionById("1895544896").getAttribute("name")); - System.out.println("测试取值name:" + SaSessionUtil.getSessionById("1895544896").getAttribute("name")); + System.out.println("自定义 session的id为:" + SaSessionCustomUtil.getSessionById("1895544896").getId()); + System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").getAttribute("name")); + SaSessionCustomUtil.getSessionById("1895544896").setAttribute("name", "张三"); // 写入值 + System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").getAttribute("name")); + System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").getAttribute("name")); return AjaxJson.getSuccess(); } diff --git a/sa-token-dev/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java b/sa-token-dev/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java index 108dea56..5ee25c94 100644 --- a/sa-token-dev/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java +++ b/sa-token-dev/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java @@ -8,8 +8,8 @@ public class SaTokenConfig { private String tokenName = "satoken"; // token名称(同时也是cookie名称) private long timeout = 30 * 24 * 60 * 60; // token有效期,单位s 默认30天,-1为永不过期 private Boolean isShare = true; // 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) - private Boolean isReadHead = false; // 是否在cookie读取不到token时,继续从请求header里继续尝试读取 - private Boolean isReadBody = false; // 是否在header读取不到token时,继续从请求题参数里继续尝试读取 + private Boolean isReadHead = true; // 是否在cookie读取不到token时,继续从请求header里继续尝试读取 + private Boolean isReadBody = true; // 是否在header读取不到token时,继续从请求题参数里继续尝试读取 private Boolean isV = true; // 是否在初始化配置时打印版本字符画 diff --git a/sa-token-dev/src/main/java/cn/dev33/satoken/session/SaSessionUtil.java b/sa-token-dev/src/main/java/cn/dev33/satoken/session/SaSessionCustomUtil.java similarity index 94% rename from sa-token-dev/src/main/java/cn/dev33/satoken/session/SaSessionUtil.java rename to sa-token-dev/src/main/java/cn/dev33/satoken/session/SaSessionCustomUtil.java index ceb57e26..e4bc306a 100644 --- a/sa-token-dev/src/main/java/cn/dev33/satoken/session/SaSessionUtil.java +++ b/sa-token-dev/src/main/java/cn/dev33/satoken/session/SaSessionCustomUtil.java @@ -3,11 +3,11 @@ package cn.dev33.satoken.session; import cn.dev33.satoken.SaTokenManager; /** - * sa-session工具类 + * 自定义sa-session工具类 * @author kong * */ -public class SaSessionUtil { +public class SaSessionCustomUtil { // 添加上指定前缀,防止恶意伪造session public static String session_key = "custom"; diff --git a/sa-token-doc/doc/.nojekyll b/sa-token-doc/doc/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/sa-token-doc/doc/README.md b/sa-token-doc/doc/README.md new file mode 100644 index 00000000..de50ae43 --- /dev/null +++ b/sa-token-doc/doc/README.md @@ -0,0 +1,49 @@ +# 介绍 + +------ + +## sa-token是什么? +一个的`JavaWeb`权限认证框架,强大、简单、好用 + + > 与其它权限认证框架相比,sa-token尽力保证两点: + > - 上手简单:能自动化的配置全部自动化,不让你费脑子 + > - 功能强大:能涵盖的功能全部涵盖,不让你用个框架还要自己给框架打各种补丁 + + +## 涵盖功能 +- 登录验证 +- 权限验证 +- 自定义session会话 +- 踢人下线 +- 模拟他人账号 +- 持久层扩展(集成redis) +- 多账号认证体系(比如一个商城项目的user表和admin表) +- 无cookie模式(APP、小程序等前后台分离场景) +- 零配置与Spring等框架集成 +- ... + + +## 贡献代码 +1. 在github上fork一份到自己的仓库 +2. clone自己的仓库到本地电脑 +3. 在本地电脑修改、commit、push +4. 提交pr(点击:New Pull Request)(提交pr前请保证自己fork的仓库是最新版本,如若不是先强制更新一下) +5. 等待合并 + +## 建议贡献的地方 +- 修复源码现有bug,或增加新的实用功能 +- 完善在线文档,或者修复现有错误之处 +- 更多demo示例:比如SSM版搭建步骤 +- 如果更新实用功能,可在文档友情链接处留下自己的推广链接 + + +## 交流群 +QQ交流群:[782974737 点击加入](https://jq.qq.com/?_wv=1027&k=5DHN5Ib) ,欢迎你的加入 + + +![扫码加群](https://color-test.oss-cn-qingdao.aliyuncs.com/sqlfly-doc/qqq.png ':size=150') + + + + + diff --git a/sa-token-doc/doc/_sidebar.md b/sa-token-doc/doc/_sidebar.md new file mode 100644 index 00000000..b79b83e3 --- /dev/null +++ b/sa-token-doc/doc/_sidebar.md @@ -0,0 +1,31 @@ + + +- **开始** + - [介绍](/README) + - [下载](/start/download) + - [示例](/start/example) + +- **使用** + - [登录验证](/use/login-auth) + - [权限验证](/use/jur-auth) + - [session会话](/use/session) + - [踢人下线](/use/kick) + - [持久层扩展](/use/dao-extend) + - [无cookie模式](/use/not-cookie) + - [模拟他人](/use/mock-person) + - [多账号验证](/use/many-account) + - [框架配置](/use/config) + +- **其它** + - [常见问题](/more/common-questions) + - [友情链接](/more/link) + - [更新日志](/more/update-log) + + + + + + + + + diff --git a/sa-token-doc/doc/index.html b/sa-token-doc/doc/index.html new file mode 100644 index 00000000..89ef3c5d --- /dev/null +++ b/sa-token-doc/doc/index.html @@ -0,0 +1,110 @@ + + + + + sa-token + + + + + + + + + + + +
+ +

sa-token

+
+
+ +
加载中...
+ + + + + + + + + diff --git a/sa-token-doc/doc/logo.png b/sa-token-doc/doc/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..88fbcde9db8fd7942b4c03068543999ba055ac60 GIT binary patch literal 4882 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 - 本篇将带你从零开始集成sa-token,从而让你快速熟悉sa-token的使用姿势 +> - 以maven + springboot为例 + +## springboot环境 + +#### 1、创建项目 +在IDE中新建一个Springboot项目,例如:`sa-token-demo-springboot`(不会的同学请自行百度或者参考github示例) + +#### 2、设置jar包依赖 +- 在项目根目录新建文件夹`lib`,将 `sa-token-spring-xxx.jar` 复制到其中 +- 并在 `pom.xml` 中添加依赖: + +``` xml + + + cn.dev33.sa-token + sa-token-spring + 1.0.0 + system + ${project.basedir}/lib/sa-token-spring-1.0.0.jar + +``` + +#### 3、配置文件 +- 你可以零配置启动项目 +- 但同时你也可以在`application.yml`中增加如下配置,定制性使用框架: + +``` java +spring: + # sa-token配置 + sa-token: + # token名称(同时也是cookie名称) + token-name: satoken + # token有效期,单位s 默认30天,-1为永不过期 + timeout: 2592000 + # 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) + is-share: true + # 是否在cookie读取不到token时,继续从请求header里继续尝试读取 + is-read-head: true + # 是否在header读取不到token时,继续从请求题参数里继续尝试读取 + is-read-body: true + # 是否在初始化配置时打印版本字符画 + is-v: true +``` + +> - 如果你习惯于 `application.properties` 类型的配置文件,那也很好办: +> - 百度: [springboot properties与yml 配置文件的区别](https://www.baidu.com/s?ie=UTF-8&wd=springboot%20properties%E4%B8%8Eyml%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%8C%BA%E5%88%AB) + +#### 4、创建主类 +在项目中新建包 `com.pj` ,在此包内新建主类 `SaTokenDemoApplication.java`,输入以下代码: + +``` java +@SaTokenSetup // 标注启动 sa-token +@SpringBootApplication +public class SaTokenDemoApplication { + public static void main(String[] args) throws JsonProcessingException { + SpringApplication.run(SaTokenDemoApplication.class, args); // run--> + System.out.println("启动成功:sa-token配置如下:" + SaTokenManager.getConfig()); + } +} +``` + +#### 5、运行 +运行代码,当你从控制台看到类似下面的内容时,就代表框架已经成功集成了 + +![运行结果](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/app-run.jpg) + + +## 普通spring环境 +- 普通spring环境与springboot环境大体无异,只不过需要在项目根目录手动创建配置文件`sa-token.properties`来完成配置 + + +## 详细了解 +通过这个示例,你已经对sa-token有了初步的了解,那么现在开始详细了解一下它都有哪些[能力](/use/login-auth)吧 + + + + + + + diff --git a/sa-token-doc/doc/use/config.md b/sa-token-doc/doc/use/config.md new file mode 100644 index 00000000..77d2e7e3 --- /dev/null +++ b/sa-token-doc/doc/use/config.md @@ -0,0 +1,68 @@ +# 框架配置 +- 你可以零配置启动框架 +- 但同时你也可以通过配置,定制性使用框架,sa-token支持多种方式配置框架信息 + +--- +### 所有可配置项 +| 参数名称 | 类型 | 默认值 | 说明 | +| :-------- | :-------- | :-------- | :-------- | +| tokenName | String | satoken | token名称(同时也是cookie名称) | +| timeout | long | 2592000 | token有效期,单位s 默认30天,-1为永不过期 | +| isShare | Boolean | true | 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) | +| isReadHead| Boolean | true | 是否在cookie读取不到token时,继续从请求header里继续尝试读取 | +| isReadBody| Boolean | true | 是否在header读取不到token时,继续从请求题参数里继续尝试读取 | +| isV | Boolean | true | 是否在初始化配置时打印版本字符画 | + + + + + +### 方式1、通过代码配置 +``` java + /** + * sa-token代码方式进行配置 + */ + @Configuration + public class MySaTokenConfig { + + // 获取配置Bean + @Primary + @Bean(name="MySaTokenConfig") + public SaTokenConfig getSaTokenConfig() { + SaTokenConfig config = new SaTokenConfig(); + config.setTokenName("satoken"); // token名称(同时也是cookie名称) + config.setTimeout(30 * 24 * 60 * 60); // token有效期,单位s 默认30天,-1为永不过期 + config.setIsShare(true); // 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) + config.setIsReadHead(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取 + config.setIsReadBody(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取 + config.setIsV(true); // 是否在初始化配置时打印版本字符画 + return config; + } + + } +``` + +### 方式2、在`application.yml`配置 + +``` java +spring: + # sa-token配置 + sa-token: + # token名称(同时也是cookie名称) + token-name: satoken + # token有效期,单位s 默认30天,-1为永不过期 + timeout: 2592000 + # 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) + is-share: true + # 是否在cookie读取不到token时,继续从请求header里继续尝试读取 + is-read-head: true + # 是否在header读取不到token时,继续从请求题参数里继续尝试读取 + is-read-body: true + # 是否在初始化配置时打印版本字符画 + is-v: true +``` + +- 如果你习惯于 `application.properties` 类型的配置文件,那也很好办: +- 百度: [springboot properties与yml 配置文件的区别](https://www.baidu.com/s?ie=UTF-8&wd=springboot%20properties%E4%B8%8Eyml%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%8C%BA%E5%88%AB) + + diff --git a/sa-token-doc/doc/use/dao-extend.md b/sa-token-doc/doc/use/dao-extend.md new file mode 100644 index 00000000..acae1d48 --- /dev/null +++ b/sa-token-doc/doc/use/dao-extend.md @@ -0,0 +1,106 @@ +# 持久层扩展 +--- +- 每次重启项目就得重新登录一遍,我想把登录数据都放在redis里,这样重启项目也不用重新登录,行不行? +- 行! +- 你需要做的就是重写`sa-token`的dao层实现方式,参考以下方案: + + +## 具体代码 +- 新建文件`SaTokenDaoRedis.java`,实现接口`SaTokenDao`, 并加上注解`@Component`,保证此类被springboot扫描到 +- 代码参考: + +```java + +package com.pj.satoken; + +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; +// import org.springframework.stereotype.Component; + +import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.session.SaSession; + +/** + * sa-token持久层的实现类 , 基于redis + */ +@Component // 保证此类被springboot扫描,即可完成sa-token与redis的集成 +public class SaTokenDaoRedis implements SaTokenDao { + + + // string专用 + @Autowired + StringRedisTemplate stringRedisTemplate; + + // SaSession专用 + RedisTemplate redisTemplate; + @Autowired + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void setRedisTemplate(RedisTemplate redisTemplate) { + RedisSerializer stringSerializer = new StringRedisSerializer(); + redisTemplate.setKeySerializer(stringSerializer); + this.redisTemplate = redisTemplate; + } + + + // 根据key获取value ,如果没有,则返回空 + @Override + public String getValue(String key) { + return stringRedisTemplate.opsForValue().get(key); + } + + // 写入指定key-value键值对,并设定过期时间(单位:秒) + @Override + public void setValue(String key, String value, long timeout) { + stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); + } + + // 删除一个指定的key + @Override + public void delKey(String key) { + stringRedisTemplate.delete(key); + } + + + // 根据指定key的session,如果没有,则返回空 + @Override + public SaSession getSaSession(String sessionId) { + return redisTemplate.opsForValue().get(sessionId); + } + + // 将指定session持久化 + @Override + public void saveSaSession(SaSession session, long timeout) { + redisTemplate.opsForValue().set(session.getId(), session, timeout, TimeUnit.SECONDS); + } + + // 更新指定session + @Override + public void updateSaSession(SaSession session) { + long expire = redisTemplate.getExpire(session.getId()); + if(expire == -2) { // -2 = 无此键 + return; + } + redisTemplate.opsForValue().set(session.getId(), session, expire, TimeUnit.SECONDS); + } + + // 删除一个指定的session + @Override + public void delSaSession(String sessionId) { + redisTemplate.delete(sessionId); + } + + + +} + + +``` + + +- 可参考代码:[码云:SaTokenDaoRedis.java](https://gitee.com/sz6/sa-token/blob/master/sa-token-demo-springboot/src/main/java/com/pj/satoken/SaTokenDaoRedis.java) + diff --git a/sa-token-doc/doc/use/jur-auth.md b/sa-token-doc/doc/use/jur-auth.md new file mode 100644 index 00000000..7610f32d --- /dev/null +++ b/sa-token-doc/doc/use/jur-auth.md @@ -0,0 +1,75 @@ +# 权限验证 +--- + + +## 核心思想 + +- 所谓权限验证,验证的核心就是当前账号是否拥有一个权限码 +- 有:就让你通过、没有:那么禁止访问 +- 再往底了说,就是每个账号都会拥有一个权限码集合,我来验证这个集合中是否包括我需要检测的那个权限码 +- 例如:当前账号拥有权限码集合:`[101, 102, "user-add", "user-get"]`,这时候我去验证权限码:`201`,则结果就是验证失败,禁止访问 +- 所以现在问题的核心就是,1、如何获取一个账号所拥有的的权限码集合,2、本次操作要验证的权限码是哪个 + +## 获取当前账号权限码集合 +因为每个项目的需求不同,其权限设计也千变万化,所以【获取当前账号权限码集合】这一操作不可能内置到框架中, +所以`sa-token`将此操作以接口的方式暴露给你,以方便的你根据自己的业务逻辑进行重写 + +- 你需要做的就是新建一个类,重写`StpInterface`接口,例如以下代码: + +``` java +package com.pj.satoken; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.stereotype.Component; +import cn.dev33.satoken.stp.StpInterface; + +/** + * 自定义权限验证接口扩展 + */ +@Component // 保证此类被springboot扫描,完成sa-token的自定义权限验证扩展 +public class StpCustom implements StpInterface { + + // 返回一个账号所拥有的权限码集合 + @Override + public List getPermissionCodeList(Object login_id, String login_key) { + List list = new ArrayList(); // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限 + list.add("101"); + list.add("user-add"); + list.add("user-delete"); + list.add("user-update"); + list.add("user-get"); + list.add("article-get"); + return list; + } + +} +``` + + +- 可参考代码:[码云:StpCustom.java](https://gitee.com/sz6/sa-token/blob/master/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpCustom.java) + + + +## 验证是否包含指定权限码 +然后就可以用以下api来鉴权了 + +#### StpUtil.hasPermission(Object pcode) +- 查询当前账号是否含有指定权限,返回true或false + +#### StpUtil.checkPermission(Object pcode) +- 检测当前账号是否含有指定权限,如果有则安全通过,如果没有则抛出异常:`NotPermissionException` + +#### StpUtil.checkPermissionAnd(Object... pcode) +- 检测当前账号是否含有指定权限【指定多个,必须全都有,否则抛出异常】 + +#### StpUtil.checkPermissionOr(Object... pcode) +- 检测当前账号是否含有指定权限【指定多个,有一个就可以了,全都没有才会抛出异常】 + + + + +## 拦截全局异常 +- 有同学要问,鉴权失败,抛出异常,然后呢?要把异常显示给用户看吗? +- 当然不能把异常抛给用户看,你可以创建一个全局异常拦截器,统一返回给前端的格式,例如以下示例: +- 参考:[码云:TopController.java](https://gitee.com/sz6/sa-token/blob/master/sa-token-demo-springboot/src/main/java/com/pj/test/TopController.java) \ No newline at end of file diff --git a/sa-token-doc/doc/use/kick.md b/sa-token-doc/doc/use/kick.md new file mode 100644 index 00000000..d91a035f --- /dev/null +++ b/sa-token-doc/doc/use/kick.md @@ -0,0 +1,15 @@ +# 踢人下线 +--- + + +## 核心思想 + +- 所谓踢人下线,核心操作就是找到其指定login_id的token,并设置其失效 + + +## 具体API + +#### StpUtil.logoutByLoginId(Object login_id) +- 让指定login_id的会话注销登录(踢人下线) + + diff --git a/sa-token-doc/doc/use/login-auth.md b/sa-token-doc/doc/use/login-auth.md new file mode 100644 index 00000000..b8c03c3e --- /dev/null +++ b/sa-token-doc/doc/use/login-auth.md @@ -0,0 +1,38 @@ +# 登录验证 +--- + + +## 核心思想 + +- 所谓登录验证,说白了就是限制某些接口只有登录后才能访问(如:查询我的账号资料) +- 如何判断你有没有登录?当然是登录成功后我给你做个标记 +- 在需要鉴权的接口里检查标记,有标记者视为已登录,无标记者视为未登录 +- 根据以上思路,我们很容易想到以下api: + + +## 具体API + +#### StpUtil.setLoginId(Object login_id) +- 标记当前会话登录的账号id +- 建议的参数类型:long | int | String, 不可以传入复杂类型,如:User、Admin等等 + +#### StpUtil.logout() +- 当前会话注销登录 + +#### StpUtil.isLogin() +- 获取当前会话是否已经登录,返回true=已登录,false=未登录 + +#### StpUtil.getLoginId() +- 获取当前会话登录id, 如果未登录,则抛出异常:`NotLoginException` +- 类似API还有: + - `StpUtil.getLoginId_asString()` 获取当前会话登录id, 并转化为String类型 + - `StpUtil.getLoginId_asInt()` 获取当前会话登录id, 并转化为int类型 + - `StpUtil.getLoginId_asLong()` 获取当前会话登录id, 并转化为long类型 + +#### StpUtil.getLoginId(T default_value) +- 获取当前会话登录id, 如果未登录,则返回默认值 (default_value可以为任意类型) +- 类似API还有: + - `StpUtil.getLoginId_defaultNull()` 获取当前会话登录id, 如果未登录,则返回null + + + diff --git a/sa-token-doc/doc/use/many-account.md b/sa-token-doc/doc/use/many-account.md new file mode 100644 index 00000000..ef2c88f7 --- /dev/null +++ b/sa-token-doc/doc/use/many-account.md @@ -0,0 +1,28 @@ +# 多账号验证 +--- + +## 问题 +- 有的时候在一个项目中,我们会设计两套账号体系,比如一个商城的user表和admin表 +- 这时候,我们就需要将两套账号的权限认证分开,防止冲突 + + +## 核心思想 +- sa-token在设计时充分考虑了多账号体系时的各种逻辑 +- 以上几篇介绍的api,都是经过 `StpUtil`类的各种静态方法进行各种验证,而如果你深入它的源码,[点此阅览](https://gitee.com/sz6/sa-token/blob/master/sa-token-dev/src/main/java/cn/dev33/satoken/stp/StpUtil.java) +- 就会发现,此类并没有任何代码逻辑,唯一做的事就是对成员变量`stpLogic`的各个API进行包装一下进行转发 +- 这样做有两个优点 + - `StpLogic`类的所有函数都可以被重写,按需扩展 + - 在构造方法时随意传入一个不同的 `login_key`,就可以再造一套账号登录体系 + +## 操作示例 +1. 新建一个新的权限验证类,比如: `StpAdminUtil.java` +2. 将`StpUtil.java`类的全部代码复制粘贴到 `StpAdminUtil.java`里 +3. 更改一下其 `login_key`, 比如: +``` + // 底层的 StpLogic 对象 + public static StpLogic stpLogic = new StpLogic("admin"); // login_key改为admin +``` +4. 接下来就可以像调用`StpUtil.java`一样调用 `StpAdminUtil.java`了,这两套账号认证的逻辑是完全隔离的 + + + diff --git a/sa-token-doc/doc/use/mock-person.md b/sa-token-doc/doc/use/mock-person.md new file mode 100644 index 00000000..d42e5674 --- /dev/null +++ b/sa-token-doc/doc/use/mock-person.md @@ -0,0 +1,24 @@ +# 模拟他人 +--- + +- 以上介绍的api都是操作当前账号,对当前账号进行各种鉴权操作,你可能会问,我能不能对别的账号进行一些操作? +- 比如:查看账号10001有无某个权限码、获取id账号为10002的用户session,等等... +- `sa-token`在api设计时充分考虑了这一点,暴露出多个api进行此类操作 + + +## 有关操作其它账号的api + +#### StpUtil.getTokenValueByLoginId(Object login_id) +- 获取指定login_id的tokenValue值 + +#### StpUtil.logoutByLoginId(Object login_id) +- 指定login_id的会话注销登录(踢人下线) + +#### StpUtil.getSessionByLoginId(Object login_id) +- 获取指定login_id的session + +#### StpUtil.hasPermission(Object login_id, Object pcode) +- 指定login_id是否含有指定权限 + + + diff --git a/sa-token-doc/doc/use/not-cookie.md b/sa-token-doc/doc/use/not-cookie.md new file mode 100644 index 00000000..aace4031 --- /dev/null +++ b/sa-token-doc/doc/use/not-cookie.md @@ -0,0 +1,47 @@ +# 无cookie模式 +--- + +## 何为无cookie + +- 常规PC端鉴权方法,一般由cookie进行 +- 而cookie有两个特性:1、可由后端控制写入,2、每次请求自动提交 +- 这就使得大多数web前端码农,无需任何特殊操作,就能完成鉴权的流程(因为整个流程都是后端控制完成的) +- 而在app、小程序等前后台分离场景中,是没有cookie这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊 +- 其实很简单 + - 不能后端控制写入了,就前端自己写入(难点在**如何将token传递到前端**) + - 每次请求不能自动提交了,那就手动提交(难点在前端如何**将token传递到后端**,同时后端**将其读取出来**) + + +## 将token传递到前端 + +1. 首先调用 `StpUtil.setLoginId(Object login_id)` 进行登录 +2. 调用 `StpUtil.getTokenInfo()` 返回当前会话的token值 + - 此方法返回一个Map,有两个key:tokenName和tokenValue(token的名称和token的值) + - 将此Map传递到前台,让前端人员将这两个值保存到本地 + +## 前端将token提交到后端 +1. 无论是app还是小程序,其传递方式都大同小异 +2. 那就是,将token塞到请求header里 ,格式为:`{tokenName: tokenValue}` +3. 以经典跨端框架`uni-app`为例: +``` + var tokenName = uni.getStorageSync('tokenName'); // 从本地缓存读取tokenName值 + var tokenValue = uni.getStorageSync('tokenValue'); // 从本地缓存读取tokenValue值 + var header = { + "content-type": "application/x-www-form-urlencoded" // 防止后台拿不到参数 + }; + if (tokenName != undefined && tokenName != '') { + header[tokenName] = tokenValue; + } + // 后续在发起请求时将 header 对象塞到请求头部 +``` + +4. 只要按照如此方法将token值传递到后端,`sa-token`就能像传统PC端一样自动读取到token值,进行鉴权 +5. 你可能会有疑问,难道我每个ajax都要写这么一坨?岂不是麻烦死了 + - 你当然不能每个ajax都写这么一坨,因为这种重复代码都是要封装在一个函数里统一调用的 + + +## 其它解决方案? +- 如果你对cookie非常了解,那你就会明白,所谓cookie,本质上就是一个特殊的header参数而已, +- 而既然它只是一个header参数,我们就能就能手动模拟实现它,从而完成鉴权操作 +- 这其实是对无cookie模式的另一种解决方案,有兴趣的同学可以百度了解一下,在此暂不赘述 + diff --git a/sa-token-doc/doc/use/session.md b/sa-token-doc/doc/use/session.md new file mode 100644 index 00000000..1298b9b9 --- /dev/null +++ b/sa-token-doc/doc/use/session.md @@ -0,0 +1,37 @@ +# session会话 +--- + + +## 账号session +账号session指的是为每个登录账号分配的session + +#### StpUtil.getSession() +- 返回当前登录账号的session(必须是登录后才能调用) + + +## 自定义session +自定义session指的是未登录状态下,以一个特定的值作为key,来分配的session + +#### SaSessionCustomUtil.isExists(String sessionId) +- 查询指定key的session,是否存在 + +#### SaSessionCustomUtil.getSessionById(String sessionId) +- 获取指定key的session,如果没有,则新建并返回 + +#### SaSessionCustomUtil.delSessionById(String sessionId) +- 删除指定key的session + + +## session相关操作 +那么获取到的`SaSession`具体有哪些方法可供操作? + +#### getId() +- 返回此session的id + +#### setAttribute(String key, Object value) +- 在此session对象上写入值 + +#### getAttribute(String key) +- 在此session对象上查询值 + +具体可参考`javax.servlet.http.HttpSession`,`SaSession`所含方法与其大体类似 \ No newline at end of file diff --git a/sa-token-doc/index.css b/sa-token-doc/index.css new file mode 100644 index 00000000..3b5c4810 --- /dev/null +++ b/sa-token-doc/index.css @@ -0,0 +1,60 @@ +/* ================================== 内容 ====================================== */ +/* 总 */ +*{margin: 0px; padding: 0px;} +body{font-size: 16px; color: #34495E; font-family: "Source Sans Pro","Helvetica Neue","Arial,sans-serif";} +header{height: 70px; border: 0px #000 solid; position: fixed; width: 100%;} +/* logo部分 */ +.logo-box {margin-top: 15px; margin-left: 30px; cursor: pointer; color: #000; float: left;} +.logo-box img {width: 50px; height: 50px; vertical-align: middle;} +.logo-box .logo-text {display: inline-block;vertical-align: middle; font-size: 22px;font-weight: 400;} +/* 右边导航 */ +.nav-right{float: right; line-height: 70px; padding-right: 4.5em;} +.nav-right a{padding: 0px 1em; color: #34495E; text-decoration: none; transition: all 0.2s;} +.nav-right a:hover{color: #42B983;} +/* 主要 */ +html,body,.main-box{width: 100%; height: 100%; } +.main-box{display: flex; align-items: center; text-align: center;} +.main-box .content-box{flex: 1;} + +.content-box h1{font-size: 110px; font-weight: 300; position: relative;} +.content-box h1 small{font-size: 20px; position: absolute; bottom: 0px;} +.sub-title{font-size: 24px; font-weight: 400; margin-top: 30px; margin-bottom: 25px;} +.content-box p{line-height: 30px;} + +.btn-box{margin-top: 16px;} +.btn-box a{ + border: 1px #42B983 solid; + border-radius: 2rem; + box-sizing: border-box; + color: #42B983; + display: inline-block; + font-size: 1.05rem; + letter-spacing: .1rem; + margin: .5rem 1rem; + padding: 0.9em 2rem; + text-decoration: none; + transition: all .15s ease; +} +/* 最后一个 */ +.btn-box a:last-child { + background-color: #42B983; + color: #fff; +} +.btn-box a:hover{color: #000;} + +/* 底部 */ +footer{ + position: fixed; + bottom: 0; + width: 100%; + line-height: 80px; + text-align: center; +} +footer a{color: inherit; text-decoration: none;} +footer a:hover{text-decoration: underline;} + +/* 媒体查询 */ +@media screen and (max-width: 800px) { + .logo-box,.copyright {display: none;} +} + diff --git a/sa-token-doc/index.html b/sa-token-doc/index.html index 0a170b28..015c8b26 100644 --- a/sa-token-doc/index.html +++ b/sa-token-doc/index.html @@ -1,11 +1,96 @@ - + - - - sa-token在线文档 + + sa-token + + + + + + + + + -

sa-token在线文档

+
+ +
+ + sa-token +
+
+ +
+ + +
+
+

sa-tokenv1.0.0

+
一个的JavaWeb权限认证框架,强大、简单、好用
+ +

登录验证、权限验证、自定义session会话、踢人下线、持久层扩展、无cookie模式、模拟他人账号、多账号体系、Spring集成...

+

零配置开箱即用,覆盖所有应用场景,你所需要的功能,这里都有

+ +
+
+ + + + + + + + - \ No newline at end of file +