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 cce96b09..d93b176e 100644 Binary files a/sa-token-demo-springboot/lib/sa-token-spring-1.0.0.jar and b/sa-token-demo-springboot/lib/sa-token-spring-1.0.0.jar differ diff --git a/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java b/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java index 384540c6..3df74e44 100644 --- a/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java +++ b/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java @@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import com.fasterxml.jackson.core.JsonProcessingException; +import cn.dev33.satoken.SaTokenManager; import cn.dev33.satoken.spring.SaTokenSetup; @SaTokenSetup // 标注启动 sa-token @@ -13,6 +14,12 @@ public class SaTokenDemoApplication { public static void main(String[] args) throws JsonProcessingException { SpringApplication.run(SaTokenDemoApplication.class, args); // run--> + 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 00000000..88fbcde9 Binary files /dev/null and b/sa-token-doc/doc/logo.png differ diff --git a/sa-token-doc/doc/more/common-questions.md b/sa-token-doc/doc/more/common-questions.md new file mode 100644 index 00000000..96c8e723 --- /dev/null +++ b/sa-token-doc/doc/more/common-questions.md @@ -0,0 +1,18 @@ +# 常见问题 + +--- + +### 用这个框架我需要很多配置吗? +- 零配置开箱即用,但同时也支持自定义配置:参考:[框架配置](use/config) + +### 如何踢人下线? +- 参考:[踢人下线](use/kick) + +### 能否集成redis? +- 参考:[无cookie模式](use/dao-extend) + +### 还是有不明白到的地方? +- 请在`github`提交`issues`,或者加入qq群交流(群链接在[首页](README?id=交流群)) + +### 我能为这个框架贡献代码吗? +- **可以**,请参照首页的提交pr步骤 ,[贡献代码](README?id=贡献代码) \ No newline at end of file diff --git a/sa-token-doc/doc/more/link.md b/sa-token-doc/doc/more/link.md new file mode 100644 index 00000000..a0c2ea13 --- /dev/null +++ b/sa-token-doc/doc/more/link.md @@ -0,0 +1,9 @@ +# 友情链接 + +--- + +- **SqlFly:**[一个好用的ORM框架](https://sqlfly.dev33.cn/) +- **sa-admin:**[一个基于多窗口后台模板, 强大、易用](http://sa-admin.dev33.cn/) +- **颜值排行榜:**[一个以颜值为讨论主题的社区](http://web.yanzhi21.com/) +- 虚位以待 + diff --git a/sa-token-doc/doc/more/update-log.md b/sa-token-doc/doc/more/update-log.md new file mode 100644 index 00000000..4626e16a --- /dev/null +++ b/sa-token-doc/doc/more/update-log.md @@ -0,0 +1,7 @@ +# 更新日志 + + +### 2020-2-4 +- 第一个版本出炉 +- GitHub:[https://github.com/click33/sa-token](https://github.com/click33/sa-token) +- gitee:[https://gitee.com/sz6/sa-token](https://gitee.com/sz6/sa-token) diff --git a/sa-token-doc/doc/start/download.md b/sa-token-doc/doc/start/download.md new file mode 100644 index 00000000..2bc1da8a --- /dev/null +++ b/sa-token-doc/doc/start/download.md @@ -0,0 +1,24 @@ +# 下载 + +------ + + +## 源码 +你可以通过`github`或者`gitee`来获取源码 +- github地址:[https://github.com/click33/sa-token](https://github.com/click33/sa-token) +- gitee地址:[https://gitee.com/sz6/sa-token](https://gitee.com/sz6/sa-token) +- 开源不易,求鼓励,给个star吧 +- 源码目录介绍 + - sa-token-dev: 源码 + - sa-token-demo-springboot: springboot集成示例 + - sa-token-doc: 文档介绍 + + +## jar包下载 +[点击下载](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/sa-token-spring-1.0.0.jar) + + + + + + diff --git a/sa-token-doc/doc/start/example.md b/sa-token-doc/doc/start/example.md new file mode 100644 index 00000000..7b369ad9 --- /dev/null +++ b/sa-token-doc/doc/start/example.md @@ -0,0 +1,85 @@ +# 示例 + +--- + +> - 本篇将带你从零开始集成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 +