mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-06-28 13:34:18 +08:00
v1.4.0更新
This commit is contained in:
parent
61647a2bba
commit
167cff595e
30
README.md
30
README.md
@ -1,12 +1,23 @@
|
||||
# sa-token
|
||||
<p align="center">
|
||||
<img alt="logo" src="http://sa-token.dev33.cn/doc/logo.png" width="150" height="150" style="margin-bottom: 10px;">
|
||||
</p>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.4.0</h1>
|
||||
<h4 align="center">一个JavaWeb权限认证框架,强大、简单、好用</h4>
|
||||
<h4 align="center">
|
||||
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.4.0-2B9939"></a>
|
||||
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/language-java-2B9939"></a>
|
||||
<a href="https://github.com/click33/sa-token/stargazers"><img src="https://img.shields.io/github/stars/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/watchers"><img src="https://img.shields.io/github/watchers/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/network/members"><img src="https://img.shields.io/github/forks/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/issues"><img src="https://img.shields.io/github/issues/click33/sa-token.svg"></a>
|
||||
<a href="https://github.com/click33/sa-token/blob/master/LICENSE"><img src="https://img.shields.io/github/license/click33/sa-token.svg"></a>
|
||||
</h4>
|
||||
|
||||
## sa-token 😋
|
||||
- 在线文档:[http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
|
||||
- 需求提交:我们深知一个优秀的项目需要海纳百川,[点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
|
||||
|
||||
一个JavaWeb权限认证框架,强大、简单、好用
|
||||
在线文档:[http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
|
||||
|
||||
:kissing_closed_eyes: :kissing_closed_eyes: :kissing_closed_eyes: :yum: :yum: :yum: :innocent: :innocent: :innocent: :heart: :heart: :heart:
|
||||
|
||||
|
||||
## 优点
|
||||
## 框架优点
|
||||
与其它权限认证框架相比,sa-token尽力保证两点:
|
||||
- 上手简单:能自动化的配置全部自动化,不让你费脑子
|
||||
- 功能强大:能涵盖的功能全部涵盖,不让你用个框架还要自己给框架打各种补丁
|
||||
@ -24,9 +35,6 @@
|
||||
- 零配置与Spring等框架集成
|
||||
- ...
|
||||
|
||||
## 需求提交
|
||||
- 我们深知一个优秀的项目需要海纳百川,[点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
|
||||
|
||||
## 贡献代码
|
||||
1. 在github上fork一份到自己的仓库
|
||||
2. clone自己的仓库到本地电脑
|
||||
|
4
sa-token-demo-springboot/.gitignore
vendored
4
sa-token-demo-springboot/.gitignore
vendored
@ -5,4 +5,6 @@ bin/
|
||||
.settings/
|
||||
unpackage/
|
||||
.classpath
|
||||
.project
|
||||
.project
|
||||
|
||||
.idea/
|
@ -25,11 +25,18 @@
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 开发测试 -->
|
||||
<!-- <dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dev</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency> -->
|
||||
|
||||
<!-- sa-token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot整合redis -->
|
||||
@ -41,44 +48,5 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!-- 配置打包 -->
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
<mainClass>com.pj.SaTokenDemoApplication</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 拷贝依赖的jar包到lib目录 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>
|
||||
${project.build.directory}/lib
|
||||
</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
@ -6,18 +6,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import cn.dev33.satoken.SaTokenManager;
|
||||
import cn.dev33.satoken.spring.SaTokenSetup;
|
||||
|
||||
@SaTokenSetup // 标注启动 sa-token
|
||||
@SaTokenSetup // 必须有这个注解,用来标注加载sa-token
|
||||
@SpringBootApplication
|
||||
public class SaTokenDemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SaTokenDemoApplication.class, args); // run-->
|
||||
SpringApplication.run(SaTokenDemoApplication.class, args);
|
||||
System.out.println("启动成功:sa-token配置如下:" + SaTokenManager.getConfig());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckInterceptor;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
|
||||
/**
|
||||
* sa-token代码方式进行配置
|
||||
@ -13,18 +16,19 @@ import cn.dev33.satoken.annotation.SaCheckInterceptor;
|
||||
public class MySaTokenConfig implements WebMvcConfigurer {
|
||||
|
||||
// 获取配置Bean (以代码的方式配置sa-token)
|
||||
// @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天
|
||||
// config.setIsShare(true); // 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
|
||||
// config.setIsReadHead(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
// config.setIsReadBody(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
// config.setIsV(true); // 是否在初始化配置时打印版本字符画
|
||||
// return config;
|
||||
// }
|
||||
@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天
|
||||
config.setIsShare(true); // 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
config.setIsReadBody(true); // 是否尝试从请求体里读取token
|
||||
config.setIsReadHead(true); // 是否尝试从header里读取token
|
||||
config.setIsReadCookie(true); // 是否尝试从cookie里读取token
|
||||
config.setIsV(true); // 是否在初始化配置时打印版本字符画
|
||||
return config;
|
||||
}
|
||||
|
||||
// 注册sa-token的拦截器,打开注解式鉴权功能
|
||||
@Override
|
||||
|
@ -9,6 +9,11 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.session.SaSessionCustomUtil;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* 测试专用Controller
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/test/")
|
||||
public class TestController {
|
||||
@ -19,22 +24,22 @@ public class TestController {
|
||||
System.out.println("======================= 进入方法,测试登录接口 ========================= ");
|
||||
System.out.println("当前会话的token:" + StpUtil.getTokenValue());
|
||||
System.out.println("当前是否登录:" + StpUtil.isLogin());
|
||||
System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull());
|
||||
System.out.println("当前登录账号:" + StpUtil.getLoginIdDefaultNull());
|
||||
StpUtil.setLoginId(id); // 在当前会话登录此账号
|
||||
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.getLoginIdAsInt()); // 获取登录id并转为int
|
||||
|
||||
// StpUtil.logout();
|
||||
// System.out.println("注销登录");
|
||||
// System.out.println("当前是否登录:" + StpUtil.isLogin());
|
||||
// System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull());
|
||||
// System.out.println("当前登录账号:" + StpUtil.getLoginIdDefaultNull());
|
||||
// StpUtil.setLoginId(id); // 在当前会话登录此账号
|
||||
// System.out.println("根据token找登录id:" + StpUtil.getLoginIdByToken(StpUtil.getTokenValue()));
|
||||
|
||||
System.out.println("当前token信息:" + StpUtil.getTokenInfo()); // 获取登录id并转为int
|
||||
System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull());
|
||||
System.out.println("当前登录账号:" + StpUtil.getLoginIdDefaultNull());
|
||||
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
@ -87,20 +92,27 @@ public class TestController {
|
||||
System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").getAttribute("name"));
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 打印当前token信息, 浏览器访问: http://localhost:8081/test/tokenInfo
|
||||
@RequestMapping("tokenInfo")
|
||||
public AjaxJson tokenInfo() {
|
||||
System.out.println("======================= 进入方法,打印当前token信息 ========================= ");
|
||||
System.out.println(StpUtil.getTokenInfo());
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
// 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/at_check
|
||||
// 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/atCheck
|
||||
@SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
|
||||
@SaCheckPermission("user-add") // 注解式鉴权:当前会话必须具有指定权限才能通过
|
||||
@RequestMapping("at_check")
|
||||
public AjaxJson at_check() {
|
||||
@RequestMapping("atCheck")
|
||||
public AjaxJson atCheck() {
|
||||
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
|
||||
System.out.println("只有通过注解鉴权,才能进入此方法");
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
|
||||
@SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
|
||||
@RequestMapping("getInfo")
|
||||
public AjaxJson getInfo() {
|
||||
return AjaxJson.getSuccessData("用户信息");
|
||||
|
@ -5,16 +5,18 @@ server:
|
||||
spring:
|
||||
# sa-token配置
|
||||
sa-token:
|
||||
# token名称(同时也是cookie名称)
|
||||
# token名称 (同时也是cookie名称)
|
||||
token-name: satoken
|
||||
# token有效期,单位s 默认30天,-1为永不过期
|
||||
# token有效期,单位s 默认30天
|
||||
timeout: 2592000
|
||||
# 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
|
||||
# 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
is-share: true
|
||||
# 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
is-read-head: true
|
||||
# 是否在header读取不到token时,继续从请求题参数里继续尝试读取
|
||||
# 是否尝试从请求体里读取token
|
||||
is-read-body: true
|
||||
# 是否尝试从header里读取token
|
||||
is-read-head: true
|
||||
# 是否尝试从cookie里读取token
|
||||
is-read-cookie: true
|
||||
# 是否在初始化配置时打印版本字符画
|
||||
is-v: true
|
||||
|
||||
@ -29,16 +31,17 @@ spring:
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password:
|
||||
# 连接池最大连接数(使用负值表示没有限制)
|
||||
pool:
|
||||
maxActive: 20
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
maxWait: -1
|
||||
# 连接池中的最大空闲连接
|
||||
maxIdle: 8
|
||||
# 连接池中的最小空闲连接
|
||||
minIdle: 1
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 0
|
||||
timeout: 1000ms
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数
|
||||
max-active: 200
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1ms
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 10
|
||||
# 连接池中的最小空闲连接
|
||||
min-idle: 0
|
||||
|
||||
|
6
sa-token-dev/.gitignore
vendored
6
sa-token-dev/.gitignore
vendored
@ -5,4 +5,8 @@ bin/
|
||||
.settings/
|
||||
unpackage/
|
||||
.classpath
|
||||
.project
|
||||
.project
|
||||
|
||||
.factorypath
|
||||
|
||||
.idea/
|
@ -7,7 +7,7 @@
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dev</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.3</version>
|
||||
<version>1.4.0</version>
|
||||
|
||||
<!-- SpringBoot -->
|
||||
<parent>
|
||||
@ -27,6 +27,13 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- @ConfigurationProperties -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@ -6,15 +6,19 @@ import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.dao.SaTokenDaoDefault;
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpInterfaceDefaultImpl;
|
||||
import cn.dev33.satoken.util.SaTokenInsideUtil;
|
||||
|
||||
/**
|
||||
* 管理sa-token所有对象
|
||||
* 管理sa-token所有对象
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenManager {
|
||||
|
||||
// 配置文件 Bean
|
||||
|
||||
/**
|
||||
* 配置文件 Bean
|
||||
*/
|
||||
private static SaTokenConfig config;
|
||||
public static SaTokenConfig getConfig() {
|
||||
if (config == null) {
|
||||
@ -25,7 +29,7 @@ public class SaTokenManager {
|
||||
public static void setConfig(SaTokenConfig config) {
|
||||
SaTokenManager.config = config;
|
||||
if(config.getIsV()) {
|
||||
SaTokenUtil.printSaToken();
|
||||
SaTokenInsideUtil.printSaToken();
|
||||
}
|
||||
}
|
||||
public synchronized static void initConfig() {
|
||||
@ -34,7 +38,10 @@ public class SaTokenManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 持久化 Bean
|
||||
|
||||
/**
|
||||
* 持久化 Bean
|
||||
*/
|
||||
public static SaTokenDao dao;
|
||||
public static SaTokenDao getDao() {
|
||||
if (dao == null) {
|
||||
@ -52,7 +59,9 @@ public class SaTokenManager {
|
||||
}
|
||||
|
||||
|
||||
// 权限认证 Bean
|
||||
/**
|
||||
* 权限认证 Bean
|
||||
*/
|
||||
public static StpInterface stp;
|
||||
public static StpInterface getStp() {
|
||||
if (stp == null) {
|
||||
|
@ -1,30 +0,0 @@
|
||||
package cn.dev33.satoken;
|
||||
|
||||
/**
|
||||
* sa-token 工具类
|
||||
*/
|
||||
public class SaTokenUtil {
|
||||
|
||||
|
||||
// sa-token 版本号
|
||||
public static final String version = "v1.0.3";
|
||||
|
||||
// sa-token 开源地址
|
||||
public static final String github_url = "https://github.com/click33/sa-token";
|
||||
|
||||
// 打印 sa-token
|
||||
public static void printSaToken() {
|
||||
String str =
|
||||
"____ ____ ___ ____ _ _ ____ _ _ \r\n" +
|
||||
"[__ |__| __ | | | |_/ |___ |\\ | \r\n" +
|
||||
"___] | | | |__| | \\_ |___ | \\| \r\n" +
|
||||
"sa-token:" + version + " \r\n" +
|
||||
"GitHub:" + github_url + "\r\n";
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
// 如果token为本次请求新创建的,则以此字符串为key存储在当前request中 JUST_CREATED_SAVE_KEY
|
||||
public static final String JUST_CREATED_SAVE_KEY= "JUST_CREATED_SAVE_KEY_";
|
||||
|
||||
|
||||
}
|
@ -11,11 +11,14 @@ import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* 注解式鉴权 - 拦截器
|
||||
* @author kong
|
||||
*/
|
||||
public class SaCheckInterceptor implements HandlerInterceptor {
|
||||
|
||||
|
||||
// 底层的 StpLogic 对象
|
||||
/**
|
||||
* 底层的 StpLogic 对象
|
||||
*/
|
||||
public StpLogic stpLogic = null;
|
||||
|
||||
/**
|
||||
@ -36,7 +39,9 @@ public class SaCheckInterceptor implements HandlerInterceptor {
|
||||
|
||||
|
||||
|
||||
// 每次请求之前触发
|
||||
/**
|
||||
* 每次请求之前触发
|
||||
*/
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
@ -62,7 +67,7 @@ public class SaCheckInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
|
||||
// 开始验证权限
|
||||
Object[] codeArray = concatABC(scp.value(), scp.valueInt(), scp.valueLong());
|
||||
Object[] codeArray = concatAbc(scp.value(), scp.valueInt(), scp.valueLong());
|
||||
if(scp.isAnd()) {
|
||||
stpLogic.checkPermissionAnd(codeArray); // 必须全部都有
|
||||
} else {
|
||||
@ -76,8 +81,14 @@ public class SaCheckInterceptor implements HandlerInterceptor {
|
||||
|
||||
|
||||
|
||||
// 合并三个数组
|
||||
private Object[] concatABC(String[] a, int[] b, long[] c) {
|
||||
/**
|
||||
* 合并三个数组
|
||||
* @param a .
|
||||
* @param b .
|
||||
* @param c .
|
||||
* @return .
|
||||
*/
|
||||
private Object[] concatAbc(String[] a, int[] b, long[] c) {
|
||||
// 循环赋值
|
||||
Object[] d = new Object[a.length + b.length + c.length];
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
|
@ -7,6 +7,8 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 标注一个路由方法,当前会话必须已登录才能通过
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
|
@ -6,7 +6,9 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 标注一个路由方法,当前会话必须具有指定权限才可以通过
|
||||
* 标注一个路由方法,当前会话必须具有指定权限才可以通过
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD,ElementType.TYPE})
|
||||
|
@ -2,14 +2,17 @@ package cn.dev33.satoken.config;
|
||||
|
||||
/**
|
||||
* sa-token 总配置类
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenConfig {
|
||||
|
||||
private String tokenName = "satoken"; // token名称(同时也是cookie名称)
|
||||
private long timeout = 30 * 24 * 60 * 60; // token有效期,单位s 默认30天
|
||||
private Boolean isShare = true; // 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
|
||||
private Boolean isReadHead = true; // 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
private Boolean isReadBody = true; // 是否在header读取不到token时,继续从请求题参数里继续尝试读取
|
||||
private String tokenName = "satoken"; // token名称 (同时也是cookie名称)
|
||||
private long timeout = 30 * 24 * 60 * 60; // token有效期,单位s 默认30天
|
||||
private Boolean isShare = true; // 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
private Boolean isReadBody = true; // 是否尝试从请求体里读取token
|
||||
private Boolean isReadHead = true; // 是否尝试从header里读取token
|
||||
private Boolean isReadCookie = true; // 是否尝试从cookie里读取token
|
||||
|
||||
private Boolean isV = true; // 是否在初始化配置时打印版本字符画
|
||||
|
||||
@ -58,6 +61,20 @@ public class SaTokenConfig {
|
||||
this.isShare = isShare;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return isReadCookie
|
||||
*/
|
||||
public Boolean getIsReadCookie() {
|
||||
return isReadCookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isReadCookie 要设置的 isReadCookie
|
||||
*/
|
||||
public void setIsReadCookie(Boolean isReadCookie) {
|
||||
this.isReadCookie = isReadCookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return isReadHead
|
||||
*/
|
||||
@ -100,14 +117,18 @@ public class SaTokenConfig {
|
||||
this.isV = isV;
|
||||
}
|
||||
|
||||
/* (非 Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaTokenConfig [tokenName=" + tokenName + ", timeout=" + timeout + ", isShare=" + isShare
|
||||
+ ", isReadHead=" + isReadHead + ", isReadBody=" + isReadBody + ", isV=" + isV + "]";
|
||||
+ ", isReadBody=" + isReadBody + ", isReadHead=" + isReadHead + ", isReadCookie=" + isReadCookie
|
||||
+ ", isV=" + isV + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -8,12 +8,17 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
创建一个配置文件
|
||||
* 创建一个配置文件
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenConfigFactory {
|
||||
|
||||
|
||||
public static String configPath = "sa-token.properties"; // 默认配置文件地址
|
||||
/**
|
||||
* 默认配置文件地址
|
||||
*/
|
||||
public static String configPath = "sa-token.properties";
|
||||
|
||||
/**
|
||||
* 根据指定路径获取配置信息
|
||||
@ -97,7 +102,7 @@ public class SaTokenConfigFactory {
|
||||
* 将字符串转化为指定数据类型
|
||||
* @param str 值
|
||||
* @param cs 要转换的类型
|
||||
* @return
|
||||
* @return .
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T>T getObjectByClass(String str, Class<T> cs){
|
||||
|
@ -4,6 +4,8 @@ import cn.dev33.satoken.session.SaSession;
|
||||
|
||||
/**
|
||||
* sa-token持久层的接口
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public interface SaTokenDao {
|
||||
|
||||
@ -11,7 +13,7 @@ public interface SaTokenDao {
|
||||
/**
|
||||
* 根据key获取value ,如果没有,则返回空
|
||||
* @param key 键名称
|
||||
* @return
|
||||
* @return value
|
||||
*/
|
||||
public String getValue(String key);
|
||||
|
||||
@ -25,7 +27,7 @@ public interface SaTokenDao {
|
||||
|
||||
/**
|
||||
* 删除一个指定的key
|
||||
* @param key
|
||||
* @param key 键名称
|
||||
*/
|
||||
public void delKey(String key);
|
||||
|
||||
@ -34,7 +36,7 @@ public interface SaTokenDao {
|
||||
/**
|
||||
* 根据指定key的session,如果没有,则返回空
|
||||
* @param sessionId 键名称
|
||||
* @return
|
||||
* @return SaSession
|
||||
*/
|
||||
public SaSession getSaSession(String sessionId);
|
||||
|
||||
|
@ -7,10 +7,14 @@ import cn.dev33.satoken.session.SaSession;
|
||||
|
||||
/**
|
||||
* sa-token持久层默认的实现类 , 基于内存Map
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenDaoDefault implements SaTokenDao {
|
||||
|
||||
// 所有数据集合
|
||||
/**
|
||||
* 所有数据集合
|
||||
*/
|
||||
Map<String, Object> dataMap = new HashMap<String, Object>();
|
||||
|
||||
|
||||
|
@ -4,6 +4,8 @@ import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* 没有登陆抛出的异常
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class NotLoginException extends RuntimeException {
|
||||
|
||||
@ -16,13 +18,13 @@ public class NotLoginException extends RuntimeException {
|
||||
/**
|
||||
* login_key
|
||||
*/
|
||||
private String login_key;
|
||||
private String loginKey;
|
||||
/**
|
||||
* 获得login_key
|
||||
* @return login_key
|
||||
*/
|
||||
public String getLoginKey() {
|
||||
return login_key;
|
||||
return loginKey;
|
||||
}
|
||||
|
||||
|
||||
@ -30,16 +32,17 @@ public class NotLoginException extends RuntimeException {
|
||||
* 创建一个
|
||||
*/
|
||||
public NotLoginException() {
|
||||
this(StpUtil.stpLogic.login_key);
|
||||
this(StpUtil.stpLogic.loginKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个
|
||||
* @param login_key login_key
|
||||
* @param loginKey login_key
|
||||
*/
|
||||
public NotLoginException(String login_key) {
|
||||
super("当前会话未登录"); // 这里到底要不要拼接上login_key呢?纠结
|
||||
this.login_key = login_key;
|
||||
public NotLoginException(String loginKey) {
|
||||
// 这里到底要不要拼接上login_key呢?纠结
|
||||
super("当前会话未登录");
|
||||
this.loginKey = loginKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* 没有指定权限码,抛出的异常
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class NotPermissionException extends RuntimeException {
|
||||
|
||||
@ -26,23 +28,24 @@ public class NotPermissionException extends RuntimeException {
|
||||
/**
|
||||
* login_key
|
||||
*/
|
||||
private String login_key;
|
||||
private String loginKey;
|
||||
/**
|
||||
* 获得login_key
|
||||
* @return login_key
|
||||
*/
|
||||
public String getLoginKey() {
|
||||
return login_key;
|
||||
return loginKey;
|
||||
}
|
||||
|
||||
|
||||
public NotPermissionException(Object code) {
|
||||
this(code, StpUtil.stpLogic.login_key);
|
||||
this(code, StpUtil.stpLogic.loginKey);
|
||||
}
|
||||
public NotPermissionException(Object code, String login_key) {
|
||||
super("无此权限:" + code); // 这里到底要不要拼接上login_key呢?纠结
|
||||
public NotPermissionException(Object code, String loginKey) {
|
||||
// 这里到底要不要拼接上login_key呢?纠结
|
||||
super("无此权限:" + code);
|
||||
this.code = code;
|
||||
this.login_key = login_key;
|
||||
this.loginKey = loginKey;
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,9 +17,18 @@ public class SaSession implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id; // 会话id
|
||||
private long createTime; // 当前会话创建时间
|
||||
private Map<String, Object> dataMap; // 当前会话键值对
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 当前会话创建时间
|
||||
*/
|
||||
private long createTime;
|
||||
/**
|
||||
* 当前会话键值对
|
||||
*/
|
||||
private Map<String, Object> dataMap;
|
||||
|
||||
|
||||
/**
|
||||
@ -34,7 +43,7 @@ public class SaSession implements Serializable {
|
||||
|
||||
/**
|
||||
* 获取会话id
|
||||
* @return
|
||||
* @return id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
@ -70,15 +79,15 @@ public class SaSession implements Serializable {
|
||||
/**
|
||||
* 取值,并指定取不到值时的默认值
|
||||
* @param key 名称
|
||||
* @param default_value 取不到值的时候返回的默认值
|
||||
* @return
|
||||
* @param defaultValue 取不到值的时候返回的默认值
|
||||
* @return value
|
||||
*/
|
||||
public Object getAttribute(String key, Object default_value) {
|
||||
public Object getAttribute(String key, Object defaultValue) {
|
||||
Object value = getAttribute(key);
|
||||
if(value != null) {
|
||||
return value;
|
||||
}
|
||||
return default_value;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,7 +9,9 @@ import cn.dev33.satoken.SaTokenManager;
|
||||
*/
|
||||
public class SaSessionCustomUtil {
|
||||
|
||||
// 添加上指定前缀,防止恶意伪造session
|
||||
/**
|
||||
* 添加上指定前缀,防止恶意伪造session
|
||||
*/
|
||||
public static String session_key = "custom";
|
||||
public static String getSessionKey(String sessionId) {
|
||||
return SaTokenManager.getConfig().getTokenName() + ":" + session_key + ":session:" + sessionId;
|
||||
@ -27,12 +29,12 @@ public class SaSessionCustomUtil {
|
||||
/**
|
||||
* 获取指定key的session
|
||||
* @param sessionId key
|
||||
* @param is_create 如果没有,是否新建并返回
|
||||
* @param isCreate 如果没有,是否新建并返回
|
||||
* @return
|
||||
*/
|
||||
public static SaSession getSessionById(String sessionId, boolean is_create) {
|
||||
public static SaSession getSessionById(String sessionId, boolean isCreate) {
|
||||
SaSession session = SaTokenManager.getDao().getSaSession(getSessionKey(sessionId));
|
||||
if(session == null && is_create) {
|
||||
if(session == null && isCreate) {
|
||||
session = new SaSession(getSessionKey(sessionId));
|
||||
SaTokenManager.getDao().saveSaSession(session, SaTokenManager.getConfig().getTimeout());
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* 将此注解加到springboot启动类上,即可完成sa-token与springboot的集成
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@Documented
|
||||
@Target({java.lang.annotation.ElementType.TYPE})
|
||||
|
@ -12,33 +12,45 @@ import cn.dev33.satoken.stp.StpInterface;
|
||||
|
||||
/**
|
||||
* 与SpringBoot集成, 保证此类被扫描,即可完成sa-token与SpringBoot的集成
|
||||
* @author kongyongshun
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class SpringSaToken {
|
||||
|
||||
|
||||
// 获取配置Bean
|
||||
/**
|
||||
* 获取配置Bean
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix="spring.sa-token")
|
||||
public SaTokenConfig getSaTokenConfig() {
|
||||
return new SaTokenConfig();
|
||||
}
|
||||
|
||||
// 注入配置Bean
|
||||
/**
|
||||
* 注入配置Bean
|
||||
* @param saTokenConfig .
|
||||
*/
|
||||
@Autowired
|
||||
public void setConfig(SaTokenConfig saTokenConfig){
|
||||
SaTokenManager.setConfig(saTokenConfig);
|
||||
}
|
||||
|
||||
// 注入持久化Bean
|
||||
/**
|
||||
* 注入持久化Bean
|
||||
* @param dao .
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setDao(SaTokenDao dao){
|
||||
SaTokenManager.setDao(dao);
|
||||
}
|
||||
|
||||
// 注入权限认证Bean
|
||||
/**
|
||||
* 注入权限认证Bean
|
||||
* @param stp .
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setStp(StpInterface stp){
|
||||
SaTokenManager.setStp(stp);
|
||||
|
@ -3,17 +3,18 @@ package cn.dev33.satoken.stp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 开放权限验证接口,方便重写
|
||||
* 开放权限验证接口,方便重写
|
||||
* @author kong
|
||||
*/
|
||||
public interface StpInterface {
|
||||
|
||||
/**
|
||||
* 返回指定login_id所拥有的权限码集合
|
||||
* @param login_id 账号id
|
||||
* @param login_key 具体的stp标识
|
||||
* @param loginId 账号id
|
||||
* @param loginKey 具体的stp标识
|
||||
* @return
|
||||
*/
|
||||
public List<Object> getPermissionCodeList(Object login_id, String login_key);
|
||||
public List<Object> getPermissionCodeList(Object loginId, String loginKey);
|
||||
|
||||
|
||||
}
|
||||
|
@ -4,12 +4,13 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限验证接口 ,默认实现
|
||||
* 权限验证接口 ,默认实现
|
||||
* @author kong
|
||||
*/
|
||||
public class StpInterfaceDefaultImpl implements StpInterface {
|
||||
|
||||
@Override
|
||||
public List<Object> getPermissionCodeList(Object login_id, String login_key) {
|
||||
public List<Object> getPermissionCodeList(Object loginId, String loginKey) {
|
||||
return new ArrayList<Object>();
|
||||
}
|
||||
|
||||
|
@ -9,30 +9,37 @@ import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import cn.dev33.satoken.SaTokenManager;
|
||||
import cn.dev33.satoken.SaTokenUtil;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.util.SaCookieUtil;
|
||||
import cn.dev33.satoken.util.SpringMVCUtil;
|
||||
import cn.dev33.satoken.util.SaTokenInsideUtil;
|
||||
import cn.dev33.satoken.util.SpringMvcUtil;
|
||||
|
||||
/**
|
||||
* sa-token 权限验证,逻辑 实现类
|
||||
* <p>
|
||||
* (stp = sa-token-permission 的缩写 )
|
||||
*
|
||||
* @author kong
|
||||
*/
|
||||
public class StpLogic {
|
||||
|
||||
/**
|
||||
* 持久化的key前缀,多账号体系时以此值区分,比如:login、user、admin
|
||||
*/
|
||||
public String loginKey = "";
|
||||
|
||||
public String login_key = ""; // 持久化的key前缀,多账号体系时以此值区分,比如:login、user、admin
|
||||
|
||||
public StpLogic(String login_key) {
|
||||
this.login_key = login_key;
|
||||
/**
|
||||
* 初始化StpLogic, 并制定loginKey
|
||||
* @param loginKey .
|
||||
*/
|
||||
public StpLogic(String loginKey) {
|
||||
this.loginKey = loginKey;
|
||||
}
|
||||
|
||||
|
||||
// =================== 获取token 相关 ===================
|
||||
|
||||
|
||||
@ -50,51 +57,49 @@ public class StpLogic {
|
||||
*/
|
||||
public String getTokenValue(){
|
||||
// 0、获取相应对象
|
||||
HttpServletRequest request = SpringMVCUtil.getRequest();
|
||||
HttpServletRequest request = SpringMvcUtil.getRequest();
|
||||
SaTokenConfig config = SaTokenManager.getConfig();
|
||||
String key_tokenName = getKey_tokenName();
|
||||
String keyTokenName = getKeyTokenName();
|
||||
|
||||
// 1、尝试从request里读取
|
||||
if(request.getAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY) != null) {
|
||||
return String.valueOf(request.getAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY));
|
||||
if(request.getAttribute(SaTokenInsideUtil.JUST_CREATED_SAVE_KEY) != null) {
|
||||
return String.valueOf(request.getAttribute(SaTokenInsideUtil.JUST_CREATED_SAVE_KEY));
|
||||
}
|
||||
|
||||
// 2、尝试从cookie里读取
|
||||
Cookie cookie = SaCookieUtil.getCookie(request, key_tokenName);
|
||||
if(cookie != null){
|
||||
String tokenValue = cookie.getValue();
|
||||
// 2、尝试从请求体里面读取
|
||||
if(config.getIsReadBody() == true){
|
||||
String tokenValue = request.getParameter(keyTokenName);
|
||||
if(tokenValue != null) {
|
||||
return tokenValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 3、尝试从header力读取
|
||||
if(config.getIsReadHead() == true){
|
||||
String tokenValue = request.getHeader(key_tokenName);
|
||||
String tokenValue = request.getHeader(keyTokenName);
|
||||
if(tokenValue != null) {
|
||||
return tokenValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 4、尝试从请求体里面读取
|
||||
if(config.getIsReadBody() == true){
|
||||
String tokenValue = request.getParameter(key_tokenName);
|
||||
if(tokenValue != null) {
|
||||
return tokenValue;
|
||||
// 4、尝试从cookie里读取
|
||||
if(config.getIsReadCookie() == true){
|
||||
Cookie cookie = SaCookieUtil.getCookie(request, keyTokenName);
|
||||
if(cookie != null){
|
||||
String tokenValue = cookie.getValue();
|
||||
if(tokenValue != null) {
|
||||
return tokenValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5、都读取不到,那算了吧还是
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定id的tokenValue
|
||||
* @param login_id
|
||||
* @param loginId .
|
||||
* @return
|
||||
*/
|
||||
public String getTokenValueByLoginId(Object login_id) {
|
||||
return SaTokenManager.getDao().getValue(getKey_LoginId(login_id));
|
||||
public String getTokenValueByLoginId(Object loginId) {
|
||||
return SaTokenManager.getDao().getValue(getKeyLoginId(loginId));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,7 +108,7 @@ public class StpLogic {
|
||||
*/
|
||||
public Map<String, String> getTokenInfo() {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("tokenName", getKey_tokenName());
|
||||
map.put("tokenName", getKeyTokenName());
|
||||
map.put("tokenValue", getTokenValue());
|
||||
return map;
|
||||
}
|
||||
@ -113,61 +118,66 @@ public class StpLogic {
|
||||
|
||||
/**
|
||||
* 在当前会话上登录id
|
||||
* @param login_id 登录id ,建议的类型:(long | int | String)
|
||||
* @param loginId 登录id ,建议的类型:(long | int | String)
|
||||
*/
|
||||
public void setLoginId(Object login_id) {
|
||||
public void setLoginId(Object loginId) {
|
||||
|
||||
// 1、获取相应对象
|
||||
HttpServletRequest request = SpringMVCUtil.getRequest();
|
||||
HttpServletRequest request = SpringMvcUtil.getRequest();
|
||||
SaTokenConfig config = SaTokenManager.getConfig();
|
||||
SaTokenDao dao = SaTokenManager.getDao();
|
||||
|
||||
// 2、获取tokenValue
|
||||
String tokenValue = getTokenValueByLoginId(login_id); // 获取旧tokenValue
|
||||
String tokenValue = getTokenValueByLoginId(loginId); // 获取旧tokenValue
|
||||
if(tokenValue == null){ // 为null则创建一个新的
|
||||
tokenValue = randomTokenValue();
|
||||
} else {
|
||||
// 不为null, 并且配置不共享,则删掉原来,并且创建新的
|
||||
if(config.getIsShare() == false){
|
||||
dao.delKey(getKey_TokenValue(tokenValue));
|
||||
dao.delKey(getKeyTokenValue(tokenValue));
|
||||
tokenValue = randomTokenValue();
|
||||
}
|
||||
}
|
||||
|
||||
// 3、持久化
|
||||
dao.setValue(getKey_TokenValue(tokenValue), String.valueOf(login_id), config.getTimeout()); // token -> uid
|
||||
dao.setValue(getKey_LoginId(login_id), tokenValue, config.getTimeout()); // uid -> token
|
||||
request.setAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY, tokenValue); // 保存到本次request里
|
||||
SaCookieUtil.addCookie(SpringMVCUtil.getResponse(), getKey_tokenName(), tokenValue, "/", (int)config.getTimeout()); // cookie注入
|
||||
dao.setValue(getKeyTokenValue(tokenValue), String.valueOf(loginId), config.getTimeout()); // token -> uid
|
||||
dao.setValue(getKeyLoginId(loginId), tokenValue, config.getTimeout()); // uid -> token
|
||||
request.setAttribute(SaTokenInsideUtil.JUST_CREATED_SAVE_KEY, tokenValue); // 保存到本次request里
|
||||
if(config.getIsReadCookie() == true){
|
||||
SaCookieUtil.addCookie(SpringMvcUtil.getResponse(), getKeyTokenName(), tokenValue, "/", (int)config.getTimeout()); // cookie注入
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前会话注销登录
|
||||
*/
|
||||
public void logout() {
|
||||
Object login_id = getLoginId_defaultNull();
|
||||
if(login_id != null) {
|
||||
logoutByLoginId(login_id);
|
||||
SaCookieUtil.delCookie(SpringMVCUtil.getRequest(), SpringMVCUtil.getResponse(), getKey_tokenName()); // 清除cookie
|
||||
Object loginId = getLoginIdDefaultNull();
|
||||
if(loginId != null) {
|
||||
logoutByLoginId(loginId);
|
||||
// 清除cookie
|
||||
if(SaTokenManager.getConfig().getIsReadCookie() == true){
|
||||
SaCookieUtil.delCookie(SpringMvcUtil.getRequest(), SpringMvcUtil.getResponse(), getKeyTokenName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定login_id的会话注销登录(踢人下线)
|
||||
* @param login_id 账号id
|
||||
* 指定loginId的会话注销登录(踢人下线)
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void logoutByLoginId(Object login_id) {
|
||||
public void logoutByLoginId(Object loginId) {
|
||||
|
||||
// 获取相应tokenValue
|
||||
String tokenValue = getTokenValueByLoginId(login_id);
|
||||
String tokenValue = getTokenValueByLoginId(loginId);
|
||||
if(tokenValue == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 清除相关数据
|
||||
SaTokenManager.getDao().delKey(getKey_TokenValue(tokenValue)); // 清除token-id键值对
|
||||
SaTokenManager.getDao().delKey(getKey_LoginId(login_id)); // 清除id-token键值对
|
||||
SaTokenManager.getDao().delKey(getKey_session(login_id)); // 清除其session
|
||||
SaTokenManager.getDao().delKey(getKeyTokenValue(tokenValue)); // 清除token-id键值对
|
||||
SaTokenManager.getDao().delKey(getKeyLoginId(loginId)); // 清除id-token键值对
|
||||
SaTokenManager.getDao().delKey(getKeySession(loginId)); // 清除其session
|
||||
// SaCookieUtil.delCookie(SpringMVCUtil.getRequest(), SpringMVCUtil.getResponse(), getKey_tokenName()); // 清除cookie
|
||||
}
|
||||
|
||||
@ -178,7 +188,7 @@ public class StpLogic {
|
||||
* @return 是否已登录
|
||||
*/
|
||||
public boolean isLogin() {
|
||||
return getLoginId_defaultNull() != null;
|
||||
return getLoginIdDefaultNull() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,49 +200,49 @@ public class StpLogic {
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则抛出异常
|
||||
* @return
|
||||
* @return .
|
||||
*/
|
||||
public Object getLoginId() {
|
||||
Object login_id = getLoginId_defaultNull();
|
||||
if(login_id == null) {
|
||||
throw new NotLoginException(this.login_key);
|
||||
Object loginId = getLoginIdDefaultNull();
|
||||
if(loginId == null) {
|
||||
throw new NotLoginException(this.loginKey);
|
||||
}
|
||||
return login_id;
|
||||
return loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则返回默认值
|
||||
* @param default_value
|
||||
* @param defaultValue .
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T>T getLoginId(T default_value) {
|
||||
Object login_id = getLoginId_defaultNull();
|
||||
if(login_id == null) {
|
||||
return default_value;
|
||||
public <T>T getLoginId(T defaultValue) {
|
||||
Object loginId = getLoginIdDefaultNull();
|
||||
if(loginId == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
if(default_value instanceof Integer) {
|
||||
return (T)Integer.valueOf(login_id.toString());
|
||||
if(defaultValue instanceof Integer) {
|
||||
return (T)Integer.valueOf(loginId.toString());
|
||||
}
|
||||
if(default_value instanceof Long) {
|
||||
return (T)Long.valueOf(login_id.toString());
|
||||
if(defaultValue instanceof Long) {
|
||||
return (T)Long.valueOf(loginId.toString());
|
||||
}
|
||||
if(default_value instanceof String) {
|
||||
return (T)login_id.toString();
|
||||
if(defaultValue instanceof String) {
|
||||
return (T)loginId.toString();
|
||||
}
|
||||
return (T)login_id;
|
||||
return (T)loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则返回null
|
||||
* @return
|
||||
*/
|
||||
public Object getLoginId_defaultNull() {
|
||||
public Object getLoginIdDefaultNull() {
|
||||
String tokenValue = getTokenValue();
|
||||
if(tokenValue != null) {
|
||||
Object login_id = SaTokenManager.getDao().getValue(getKey_TokenValue(tokenValue));
|
||||
if(login_id != null) {
|
||||
return login_id;
|
||||
Object loginId = SaTokenManager.getDao().getValue(getKeyTokenValue(tokenValue));
|
||||
if(loginId != null) {
|
||||
return loginId;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -242,7 +252,7 @@ public class StpLogic {
|
||||
* 获取当前会话登录id, 并转换为String
|
||||
* @return
|
||||
*/
|
||||
public String getLoginId_asString() {
|
||||
public String getLoginIdAsString() {
|
||||
return String.valueOf(getLoginId());
|
||||
}
|
||||
|
||||
@ -250,10 +260,10 @@ public class StpLogic {
|
||||
* 获取当前会话登录id, 并转换为int
|
||||
* @return
|
||||
*/
|
||||
public int getLoginId_asInt() {
|
||||
// Object login_id = getLoginId();
|
||||
// if(login_id instanceof Integer) {
|
||||
// return (Integer)login_id;
|
||||
public int getLoginIdAsInt() {
|
||||
// Object loginId = getLoginId();
|
||||
// if(loginId instanceof Integer) {
|
||||
// return (Integer)loginId;
|
||||
// }
|
||||
return Integer.valueOf(String.valueOf(getLoginId()));
|
||||
}
|
||||
@ -262,23 +272,23 @@ public class StpLogic {
|
||||
* 获取当前会话登录id, 并转换为long
|
||||
* @return
|
||||
*/
|
||||
public long getLoginId_asLong() {
|
||||
// Object login_id = getLoginId();
|
||||
// if(login_id instanceof Long) {
|
||||
// return (Long)login_id;
|
||||
public long getLoginIdAsLong() {
|
||||
// Object loginId = getLoginId();
|
||||
// if(loginId instanceof Long) {
|
||||
// return (Long)loginId;
|
||||
// }
|
||||
return Long.valueOf(String.valueOf(getLoginId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定token对应的登录id,如果未登录,则返回 null
|
||||
* @return
|
||||
* @return .
|
||||
*/
|
||||
public Object getLoginIdByToken(String tokenValue) {
|
||||
if(tokenValue != null) {
|
||||
Object login_id = SaTokenManager.getDao().getValue(getKey_TokenValue(tokenValue));
|
||||
if(login_id != null) {
|
||||
return login_id;
|
||||
Object loginId = SaTokenManager.getDao().getValue(getKeyTokenValue(tokenValue));
|
||||
if(loginId != null) {
|
||||
return loginId;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -288,14 +298,14 @@ public class StpLogic {
|
||||
// =================== session相关 ===================
|
||||
|
||||
/**
|
||||
* 获取指定key的session, 如果没有,is_create=是否新建并返回
|
||||
* @param sessionId
|
||||
* @param is_create
|
||||
* @return
|
||||
* 获取指定key的session, 如果没有,isCreate=是否新建并返回
|
||||
* @param sessionId .
|
||||
* @param isCreate .
|
||||
* @return .
|
||||
*/
|
||||
protected SaSession getSessionBySessionId(String sessionId, boolean is_create) {
|
||||
protected SaSession getSessionBySessionId(String sessionId, boolean isCreate) {
|
||||
SaSession session = SaTokenManager.getDao().getSaSession(sessionId);
|
||||
if(session == null && is_create) {
|
||||
if(session == null && isCreate) {
|
||||
session = new SaSession(sessionId);
|
||||
SaTokenManager.getDao().saveSaSession(session, SaTokenManager.getConfig().getTimeout());
|
||||
}
|
||||
@ -303,20 +313,30 @@ public class StpLogic {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定login_id的session
|
||||
* @param login_id
|
||||
* @return
|
||||
* 获取指定loginId的session, 如果没有,isCreate=是否新建并返回
|
||||
* @param loginId 登录id
|
||||
* @param isCreate 是否新建
|
||||
* @return SaSession
|
||||
*/
|
||||
public SaSession getSessionByLoginId(Object login_id) {
|
||||
return getSessionBySessionId(getKey_session(login_id), false);
|
||||
public SaSession getSessionByLoginId(Object loginId, boolean isCreate) {
|
||||
return getSessionBySessionId(getKeySession(loginId), isCreate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定loginId的session
|
||||
* @param loginId .
|
||||
* @return .
|
||||
*/
|
||||
public SaSession getSessionByLoginId(Object loginId) {
|
||||
return getSessionByLoginId(getKeySession(loginId), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的session
|
||||
* @return
|
||||
*/
|
||||
public SaSession getSession() {
|
||||
return getSessionBySessionId(getKey_session(getLoginId()), true);
|
||||
return getSessionBySessionId(getKeySession(getLoginId()), true);
|
||||
}
|
||||
|
||||
|
||||
@ -324,20 +344,20 @@ public class StpLogic {
|
||||
// =================== 权限验证操作 ===================
|
||||
|
||||
/**
|
||||
* 指定login_id是否含有指定权限
|
||||
* @param login_id
|
||||
* @param pcode
|
||||
* @return
|
||||
* 指定loginId是否含有指定权限
|
||||
* @param loginId .
|
||||
* @param pcode .
|
||||
* @return .
|
||||
*/
|
||||
public boolean hasPermission(Object login_id, Object pcode) {
|
||||
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
|
||||
public boolean hasPermission(Object loginId, Object pcode) {
|
||||
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(loginId, loginKey);
|
||||
return !(pcodeList == null || pcodeList.contains(pcode) == false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前会话是否含有指定权限
|
||||
* @param pcode
|
||||
* @return
|
||||
* @param pcode .
|
||||
* @return .
|
||||
*/
|
||||
public boolean hasPermission(Object pcode) {
|
||||
return hasPermission(getLoginId(), pcode);
|
||||
@ -345,42 +365,42 @@ public class StpLogic {
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 没有就抛出异常
|
||||
* @param pcode
|
||||
* @param pcode .
|
||||
*/
|
||||
public void checkPermission(Object pcode) {
|
||||
if(hasPermission(pcode) == false) {
|
||||
throw new NotPermissionException(pcode, this.login_key);
|
||||
throw new NotPermissionException(pcode, this.loginKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 【指定多个,必须全都有】
|
||||
* @param pcodeArray
|
||||
* @param pcodeArray .
|
||||
*/
|
||||
public void checkPermissionAnd(Object... pcodeArray){
|
||||
Object login_id = getLoginId();
|
||||
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
|
||||
Object loginId = getLoginId();
|
||||
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(loginId, loginKey);
|
||||
for (Object pcode : pcodeArray) {
|
||||
if(pcodeList.contains(pcode) == false) {
|
||||
throw new NotPermissionException(pcode, this.login_key); // 没有权限抛出异常
|
||||
throw new NotPermissionException(pcode, this.loginKey); // 没有权限抛出异常
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 【指定多个,有一个就可以了】
|
||||
* @param pcodeArray
|
||||
* @param pcodeArray .
|
||||
*/
|
||||
public void checkPermissionOr(Object... pcodeArray){
|
||||
Object login_id = getLoginId();
|
||||
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
|
||||
Object loginId = getLoginId();
|
||||
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(loginId, loginKey);
|
||||
for (Object pcode : pcodeArray) {
|
||||
if(pcodeList.contains(pcode) == true) {
|
||||
return; // 有的话提前退出
|
||||
}
|
||||
}
|
||||
if(pcodeArray.length > 0) {
|
||||
throw new NotPermissionException(pcodeArray[0], this.login_key); // 没有权限抛出异常
|
||||
throw new NotPermissionException(pcodeArray[0], this.loginKey); // 没有权限抛出异常
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,32 +411,32 @@ public class StpLogic {
|
||||
* 获取key:客户端 tokenName
|
||||
* @return
|
||||
*/
|
||||
public String getKey_tokenName() {
|
||||
public String getKeyTokenName() {
|
||||
return SaTokenManager.getConfig().getTokenName();
|
||||
}
|
||||
/**
|
||||
* 获取key: tokenValue 持久化
|
||||
* @param tokenValue
|
||||
* @param tokenValue .
|
||||
* @return
|
||||
*/
|
||||
public String getKey_TokenValue(String tokenValue) {
|
||||
return SaTokenManager.getConfig().getTokenName() + ":" + login_key + ":token:" + tokenValue;
|
||||
public String getKeyTokenValue(String tokenValue) {
|
||||
return SaTokenManager.getConfig().getTokenName() + ":" + loginKey + ":token:" + tokenValue;
|
||||
}
|
||||
/**
|
||||
* 获取key: id 持久化
|
||||
* @param login_id
|
||||
* @param loginId .
|
||||
* @return
|
||||
*/
|
||||
public String getKey_LoginId(Object login_id) {
|
||||
return SaTokenManager.getConfig().getTokenName() + ":" + login_key + ":id:" + login_id;
|
||||
public String getKeyLoginId(Object loginId) {
|
||||
return SaTokenManager.getConfig().getTokenName() + ":" + loginKey + ":id:" + loginId;
|
||||
}
|
||||
/**
|
||||
* 获取key: session 持久化
|
||||
* @param login_id
|
||||
* @return
|
||||
* @param loginId .
|
||||
* @return .
|
||||
*/
|
||||
public String getKey_session(Object login_id) {
|
||||
return SaTokenManager.getConfig().getTokenName() + ":" + login_key + ":session:" + login_id;
|
||||
public String getKeySession(Object loginId) {
|
||||
return SaTokenManager.getConfig().getTokenName() + ":" + loginKey + ":session:" + loginId;
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,11 +8,14 @@ import cn.dev33.satoken.session.SaSession;
|
||||
|
||||
/**
|
||||
* 一个默认的实现
|
||||
* @author kong
|
||||
*/
|
||||
@Service
|
||||
public class StpUtil {
|
||||
|
||||
// 底层的 StpLogic 对象
|
||||
/**
|
||||
* 底层的 StpLogic 对象
|
||||
*/
|
||||
public static StpLogic stpLogic = new StpLogic("login");
|
||||
|
||||
|
||||
@ -29,11 +32,11 @@ public class StpUtil {
|
||||
|
||||
/**
|
||||
* 获取指定id的tokenValue
|
||||
* @param login_id
|
||||
* @param loginId .
|
||||
* @return
|
||||
*/
|
||||
public static String getTokenValueByLoginId(Object login_id) {
|
||||
return stpLogic.getTokenValueByLoginId(login_id);
|
||||
public static String getTokenValueByLoginId(Object loginId) {
|
||||
return stpLogic.getTokenValueByLoginId(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,10 +51,10 @@ public class StpUtil {
|
||||
|
||||
/**
|
||||
* 在当前会话上登录id
|
||||
* @param login_id 登录id ,建议的类型:(long | int | String)
|
||||
* @param loginId 登录id ,建议的类型:(long | int | String)
|
||||
*/
|
||||
public static void setLoginId(Object login_id) {
|
||||
stpLogic.setLoginId(login_id);
|
||||
public static void setLoginId(Object loginId) {
|
||||
stpLogic.setLoginId(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,11 +65,11 @@ public class StpUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定login_id的会话注销登录(踢人下线)
|
||||
* @param login_id 账号id
|
||||
* 指定loginId的会话注销登录(踢人下线)
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public static void logoutByLoginId(Object login_id) {
|
||||
stpLogic.logoutByLoginId(login_id);
|
||||
public static void logoutByLoginId(Object loginId) {
|
||||
stpLogic.logoutByLoginId(loginId);
|
||||
}
|
||||
|
||||
// 查询相关
|
||||
@ -88,7 +91,7 @@ public class StpUtil {
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则抛出异常
|
||||
* @return
|
||||
* @return .
|
||||
*/
|
||||
public static Object getLoginId() {
|
||||
return stpLogic.getLoginId();
|
||||
@ -96,48 +99,48 @@ public class StpUtil {
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则返回默认值
|
||||
* @param default_value
|
||||
* @return
|
||||
* @param defaultValue .
|
||||
* @return .
|
||||
*/
|
||||
public static <T> T getLoginId(T default_value) {
|
||||
return stpLogic.getLoginId(default_value);
|
||||
public static <T> T getLoginId(T defaultValue) {
|
||||
return stpLogic.getLoginId(defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则返回null
|
||||
* @return
|
||||
*/
|
||||
public static Object getLoginId_defaultNull() {
|
||||
return stpLogic.getLoginId_defaultNull();
|
||||
public static Object getLoginIdDefaultNull() {
|
||||
return stpLogic.getLoginIdDefaultNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 并转换为String
|
||||
* @return
|
||||
*/
|
||||
public static String getLoginId_asString() {
|
||||
return stpLogic.getLoginId_asString();
|
||||
public static String getLoginIdAsString() {
|
||||
return stpLogic.getLoginIdAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 并转换为int
|
||||
* @return
|
||||
*/
|
||||
public static int getLoginId_asInt() {
|
||||
return stpLogic.getLoginId_asInt();
|
||||
public static int getLoginIdAsInt() {
|
||||
return stpLogic.getLoginIdAsInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 并转换为long
|
||||
* @return
|
||||
*/
|
||||
public static long getLoginId_asLong() {
|
||||
return stpLogic.getLoginId_asLong();
|
||||
public static long getLoginIdAsLong() {
|
||||
return stpLogic.getLoginIdAsLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定token对应的登录id,如果未登录,则返回 null
|
||||
* @return
|
||||
* @return .
|
||||
*/
|
||||
public static Object getLoginIdByToken(String tokenValue) {
|
||||
return stpLogic.getLoginIdByToken(tokenValue);
|
||||
@ -146,14 +149,24 @@ public class StpUtil {
|
||||
// =================== session相关 ===================
|
||||
|
||||
/**
|
||||
* 获取指定login_id的session
|
||||
* @param login_id
|
||||
* @return
|
||||
* 获取指定loginId的session, 如果没有,isCreate=是否新建并返回
|
||||
* @param loginId 登录id
|
||||
* @param isCreate 是否新建
|
||||
* @return SaSession
|
||||
*/
|
||||
public static SaSession getSessionByLoginId(Object login_id) {
|
||||
return stpLogic.getSessionByLoginId(login_id);
|
||||
public static SaSession getSessionByLoginId(Object loginId, boolean isCreate) {
|
||||
return stpLogic.getSessionByLoginId(loginId, isCreate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定loginId的session
|
||||
* @param loginId .
|
||||
* @return .
|
||||
*/
|
||||
public static SaSession getSessionByLoginId(Object loginId) {
|
||||
return stpLogic.getSessionByLoginId(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的session
|
||||
* @return
|
||||
@ -165,19 +178,19 @@ public class StpUtil {
|
||||
// =================== 权限验证操作 ===================
|
||||
|
||||
/**
|
||||
* 指定login_id是否含有指定权限
|
||||
* @param login_id
|
||||
* @param pcode
|
||||
* @return
|
||||
* 指定loginId是否含有指定权限
|
||||
* @param loginId .
|
||||
* @param pcode .
|
||||
* @return .
|
||||
*/
|
||||
public static boolean hasPermission(Object login_id, Object pcode) {
|
||||
return stpLogic.hasPermission(login_id, pcode);
|
||||
public static boolean hasPermission(Object loginId, Object pcode) {
|
||||
return stpLogic.hasPermission(loginId, pcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前会话是否含有指定权限
|
||||
* @param pcode
|
||||
* @return
|
||||
* @param pcode .
|
||||
* @return .
|
||||
*/
|
||||
public static boolean hasPermission(Object pcode) {
|
||||
return stpLogic.hasPermission(pcode);
|
||||
@ -185,7 +198,7 @@ public class StpUtil {
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 没有就抛出异常
|
||||
* @param pcode
|
||||
* @param pcode .
|
||||
*/
|
||||
public static void checkPermission(Object pcode) {
|
||||
stpLogic.checkPermission(pcode);
|
||||
@ -193,7 +206,7 @@ public class StpUtil {
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 【指定多个,必须全都有】
|
||||
* @param pcodeArray
|
||||
* @param pcodeArray .
|
||||
*/
|
||||
public static void checkPermissionAnd(Object... pcodeArray) {
|
||||
stpLogic.checkPermissionAnd(pcodeArray);
|
||||
@ -201,7 +214,7 @@ public class StpUtil {
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 【指定多个,有一个就可以了】
|
||||
* @param pcodeArray
|
||||
* @param pcodeArray .
|
||||
*/
|
||||
public static void checkPermissionOr(Object... pcodeArray) {
|
||||
stpLogic.checkPermissionOr(pcodeArray);
|
||||
|
@ -14,10 +14,10 @@ public class SaCookieUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定cookie
|
||||
* @param request
|
||||
* @param cookieName
|
||||
* @return
|
||||
* 获取指定cookie .
|
||||
* @param request .
|
||||
* @param cookieName .
|
||||
* @return .
|
||||
*/
|
||||
public static Cookie getCookie(HttpServletRequest request, String cookieName) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
@ -35,11 +35,11 @@ public class SaCookieUtil {
|
||||
|
||||
/**
|
||||
* 添加cookie
|
||||
* @param response
|
||||
* @param name
|
||||
* @param value
|
||||
* @param path
|
||||
* @param timeout
|
||||
* @param response .
|
||||
* @param name .
|
||||
* @param value .
|
||||
* @param path .
|
||||
* @param timeout .
|
||||
*/
|
||||
public static void addCookie(HttpServletResponse response,String name,String value,String path,int timeout) {
|
||||
Cookie cookie = new Cookie(name, value);
|
||||
@ -53,10 +53,10 @@ public class SaCookieUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 删除cookie
|
||||
* @param request
|
||||
* @param response
|
||||
* @param name
|
||||
* 删除cookie .
|
||||
* @param request .
|
||||
* @param response .
|
||||
* @param name .
|
||||
*/
|
||||
public static void delCookie(HttpServletRequest request,HttpServletResponse response,String name) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
@ -73,10 +73,10 @@ public class SaCookieUtil {
|
||||
|
||||
/**
|
||||
* 修改cookie的value值
|
||||
* @param request
|
||||
* @param response
|
||||
* @param name
|
||||
* @param value
|
||||
* @param request .
|
||||
* @param response .
|
||||
* @param name .
|
||||
* @param value .
|
||||
*/
|
||||
public static void updateCookie(HttpServletRequest request,HttpServletResponse response,String name,String value) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
|
@ -0,0 +1,40 @@
|
||||
package cn.dev33.satoken.util;
|
||||
|
||||
/**
|
||||
* sa-token 工具类
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenInsideUtil {
|
||||
|
||||
|
||||
/**
|
||||
* sa-token 版本号
|
||||
*/
|
||||
public static final String VERSION_NO = "v1.4.0";
|
||||
|
||||
/**
|
||||
* sa-token 开源地址
|
||||
*/
|
||||
public static final String GITHUB_URL= "https://github.com/click33/sa-token";
|
||||
|
||||
/**
|
||||
* 打印 sa-token
|
||||
*/
|
||||
public static void printSaToken() {
|
||||
String str =
|
||||
"____ ____ ___ ____ _ _ ____ _ _ \r\n" +
|
||||
"[__ |__| __ | | | |_/ |___ |\\ | \r\n" +
|
||||
"___] | | | |__| | \\_ |___ | \\| \r\n" +
|
||||
"sa-token:" + VERSION_NO + " \r\n" +
|
||||
"GitHub:" + GITHUB_URL; // + "\r\n";
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果token为本次请求新创建的,则以此字符串为key存储在当前request中 JUST_CREATED_SAVE_KEY
|
||||
*/
|
||||
public static final String JUST_CREATED_SAVE_KEY = "JUST_CREATED_SAVE_KEY_";
|
||||
|
||||
|
||||
}
|
@ -11,7 +11,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SpringMVCUtil {
|
||||
public class SpringMvcUtil {
|
||||
|
||||
/**
|
||||
* 获取当前会话的 request
|
||||
@ -37,4 +37,7 @@ public class SpringMVCUtil {
|
||||
return servletRequestAttributes.getResponse();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package com.pj;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import cn.dev33.satoken.SaTokenManager;
|
||||
import cn.dev33.satoken.spring.SaTokenSetup;
|
||||
|
||||
@SaTokenSetup // 标注启动 sa-token
|
||||
@SpringBootApplication
|
||||
public class SaTokenApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SaTokenApplication.class, args); // run-->
|
||||
System.out.println(SaTokenManager.getConfig());
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
# 端口
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
spring:
|
||||
# sa-token配置
|
||||
sa-token:
|
||||
# token名称(同时也是cookie名称)
|
||||
token-name: satoken
|
||||
# token有效期,单位s 默认30天
|
||||
timeout: 2592000
|
||||
# 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
|
||||
is-share: true
|
||||
# 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
is-read-head: true
|
||||
# 是否在header读取不到token时,继续从请求题参数里继续尝试读取
|
||||
is-read-body: true
|
||||
# 是否在初始化配置时打印版本字符画
|
||||
is-v: true
|
||||
|
@ -1,12 +1,25 @@
|
||||
# sa-token
|
||||
<p align="center">
|
||||
<img alt="logo" src="http://sa-token.dev33.cn/doc/logo.png" width="150" height="150" style="margin-bottom: 10px;">
|
||||
</p>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.4.0</h1>
|
||||
<h4 align="center">一个JavaWeb权限认证框架,强大、简单、好用</h4>
|
||||
<h4 align="center">
|
||||
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.4.0-2B9939"></a>
|
||||
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/language-java-2B9939"></a>
|
||||
<a href="https://github.com/click33/sa-token/stargazers"><img src="https://img.shields.io/github/stars/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/watchers"><img src="https://img.shields.io/github/watchers/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/network/members"><img src="https://img.shields.io/github/forks/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/issues"><img src="https://img.shields.io/github/issues/click33/sa-token.svg"></a>
|
||||
<a href="https://github.com/click33/sa-token/blob/master/LICENSE"><img src="https://img.shields.io/github/license/click33/sa-token.svg"></a>
|
||||
</h4>
|
||||
|
||||
一个JavaWeb权限认证框架,强大、简单、好用
|
||||
在线文档:[http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
|
||||
---
|
||||
|
||||
## sa-token 😋
|
||||
- 在线文档:[http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
|
||||
- 需求提交:我们深知一个优秀的项目需要海纳百川,[点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
|
||||
|
||||
:kissing_closed_eyes: :kissing_closed_eyes: :kissing_closed_eyes: :yum: :yum: :yum: :innocent: :innocent: :innocent: :heart: :heart: :heart:
|
||||
|
||||
|
||||
## 优点
|
||||
## 框架优点
|
||||
与其它权限认证框架相比,sa-token尽力保证两点:
|
||||
- 上手简单:能自动化的配置全部自动化,不让你费脑子
|
||||
- 功能强大:能涵盖的功能全部涵盖,不让你用个框架还要自己给框架打各种补丁
|
||||
@ -24,9 +37,6 @@
|
||||
- 零配置与Spring等框架集成
|
||||
- ...
|
||||
|
||||
## 需求提交
|
||||
- 我们深知一个优秀的项目需要海纳百川,[点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
|
||||
|
||||
## 贡献代码
|
||||
1. 在github上fork一份到自己的仓库
|
||||
2. clone自己的仓库到本地电脑
|
||||
|
@ -28,7 +28,7 @@
|
||||
<div id="app">加载中...</div>
|
||||
<script>
|
||||
var name = '<img style="width: 50px; height: 50px; vertical-align: middle;" src="logo.png" alt="logo" /> ';
|
||||
name += '<b style="font-size: 24px; vertical-align: middle;">sa-token</b> <sub>v1.0.3</sub>'
|
||||
name += '<b style="font-size: 24px; vertical-align: middle;">sa-token</b> <sub>v1.4.0</sub>'
|
||||
window.$docsify = {
|
||||
name: name, // 名字
|
||||
repo: 'https://github.com/click33/sa-token', // github地址
|
||||
|
BIN
sa-token-doc/doc/logo-150.png
Normal file
BIN
sa-token-doc/doc/logo-150.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
@ -4,7 +4,7 @@
|
||||
|
||||
- **sa-admin:**[一个多窗口后台模板,流畅、易上手、提高生产力](http://sa-admin.dev33.cn/)
|
||||
- **sa-vue-admin:**[对sa-admin的vue单页版实现, 基于vue-cli、element-ui的单页后台模板](http://sa-vue-admin.dev33.cn/)
|
||||
- **sa-fast:**[一个基于springboot架构的快速开发平台,内置代码生成器,吹灰之力快速CRUD](http://sa-fast.dev33.cn/)
|
||||
- **sa-plus:**[一个基于springboot架构的快速开发平台,内置代码生成器,吹灰之力快速CRUD](http://sa-plus.dev33.cn/)
|
||||
- **sa-doc:**[一个基于markdown的接口文档编写工具](http://sa-doc.dev33.cn/)
|
||||
- **SqlFly:**[一个java语言的ORM框架](https://sqlfly.dev33.cn/)
|
||||
- 虚位以待
|
||||
|
@ -1,10 +1,17 @@
|
||||
# 更新日志
|
||||
|
||||
### 2020-9-7 @v1.4.0
|
||||
- 优化:修改一些函数、变量名称,使其更符合阿里java代码规范
|
||||
- 优化:`tokenValue`的读取优先级改为:`request` > `body` > `header` > `cookie`
|
||||
- 新增:新增`isReadCookie`配置,决定是否从`cookie`里读取`token`信息
|
||||
- 优化:如果`isReadCookie`配置为`false`,那么在登录时也不会把`cookie`写入`cookie`
|
||||
- 新增:新增`getSessionByLoginId(Object loginId, boolean isCreate)`方法
|
||||
- 修复:修复文档部分错误,修正群号码
|
||||
|
||||
### 2020-5-2 @v1.0.3
|
||||
- 新增:新增 `StpUtil.checkLogin()` 方法,更符合语义化的鉴权方法
|
||||
- 新增:注册拦截器时可设置 `StpLogic` ,方便不同模块不同鉴权方式
|
||||
- 新增:抛出异常时增加 `login_key` 区分,方便多账号体系鉴权处理
|
||||
- 新增:抛出异常时增加 `loginKey` 区分,方便多账号体系鉴权处理
|
||||
- 修复:修复启动时的版本字符画版本号打印不对的bug
|
||||
- 修复:修复文档部分不正确之处
|
||||
- 新增:新增文档的友情链接
|
||||
@ -14,7 +21,7 @@
|
||||
- 参考:[注解式验证](use/at-check)
|
||||
|
||||
### 2020-2-12 @v1.0.1
|
||||
- 修复:修复`StpUtil.getLoginId(T default_value)`取值转换错误的bug
|
||||
- 修复:修复`StpUtil.getLoginId(T defaultValue)`取值转换错误的bug
|
||||
|
||||
### 2020-2-4 @v1.0.0
|
||||
- 第一个版本出炉
|
||||
|
@ -9,18 +9,18 @@
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## 源码
|
||||
## 获取源码
|
||||
如果你想深入了解`sa-token`,你可以通过`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吧
|
||||
- 开源不易,求鼓励,给个`star`吧
|
||||
- 源码目录介绍
|
||||
- sa-token-dev: 源码
|
||||
- sa-token-demo-springboot: springboot集成示例
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
|
||||
## jar包下载
|
||||
[点击下载:sa-token-1.0.3.jar](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/sa-token-1.0.3.jar)
|
||||
[点击下载:sa-token-1.4.0.jar](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/sa-token-1.4.0.jar)
|
||||
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
- 尽管我们可以方便的一句代码完成权限验证,但是有时候我们仍希望可以将鉴权代码与我们的业务代码分离开来
|
||||
- 怎么做?
|
||||
- sa-token内置两个注解,帮助你使用注解完成鉴权操作
|
||||
- `sa-token`内置两个注解,帮助你使用注解完成鉴权操作
|
||||
|
||||
|
||||
## 1、注册拦截器
|
||||
@ -21,7 +21,7 @@
|
||||
}
|
||||
}
|
||||
```
|
||||
- 保证此类被springboot启动类扫描到
|
||||
- 保证此类被`springboot`启动类扫描到
|
||||
|
||||
## 2、使用注解
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
# 框架配置
|
||||
- 你可以零配置启动框架
|
||||
- 但同时你也可以通过配置,定制性使用框架,sa-token支持多种方式配置框架信息
|
||||
- 但同时你也可以通过配置,定制性使用框架,`sa-token`支持多种方式配置框架信息
|
||||
|
||||
---
|
||||
### 所有可配置项
|
||||
| 参数名称 | 类型 | 默认值 | 说明 |
|
||||
| :-------- | :-------- | :-------- | :-------- |
|
||||
| tokenName | String | satoken | token名称(同时也是cookie名称) |
|
||||
| timeout | long | 2592000 | token有效期,单位s 默认30天 |
|
||||
| isShare | Boolean | true | 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) |
|
||||
| isReadHead| Boolean | true | 是否在cookie读取不到token时,继续从请求header里继续尝试读取 |
|
||||
| isReadBody| Boolean | true | 是否在header读取不到token时,继续从请求题参数里继续尝试读取 |
|
||||
| isV | Boolean | true | 是否在初始化配置时打印版本字符画 |
|
||||
| 参数名称 | 类型 | 默认值 | 说明 |
|
||||
| :-------- | :-------- | :-------- | :-------- |
|
||||
| tokenName | String | satoken | token名称(同时也是cookie名称) |
|
||||
| timeout | long | 2592000 | token有效期,单位s 默认30天 |
|
||||
| isShare | Boolean | true | 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)|
|
||||
| isReadBody | Boolean | true | 是否尝试从请求体里读取token |
|
||||
| isReadHead | Boolean | true | 是否尝试从header里读取token |
|
||||
| isReadCookie | Boolean | true | 是否尝试从cookie里读取token |
|
||||
| isV | Boolean | true | 是否在初始化配置时打印版本字符画 |
|
||||
|
||||
|
||||
|
||||
@ -25,16 +26,17 @@
|
||||
@Configuration
|
||||
public class MySaTokenConfig {
|
||||
|
||||
// 获取配置Bean
|
||||
// 获取配置Bean (以代码的方式配置sa-token)
|
||||
@Primary
|
||||
@Bean(name="MySaTokenConfig")
|
||||
public SaTokenConfig getSaTokenConfig() {
|
||||
SaTokenConfig config = new SaTokenConfig();
|
||||
config.setTokenName("satoken"); // token名称(同时也是cookie名称)
|
||||
config.setTokenName("satoken"); // token名称 (同时也是cookie名称)
|
||||
config.setTimeout(30 * 24 * 60 * 60); // token有效期,单位s 默认30天
|
||||
config.setIsShare(true); // 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
|
||||
config.setIsReadHead(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
config.setIsReadBody(true); // 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
config.setIsShare(true); // 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
config.setIsReadBody(true); // 是否尝试从请求体里读取token
|
||||
config.setIsReadHead(true); // 是否尝试从header里读取token
|
||||
config.setIsReadCookie(true); // 是否尝试从cookie里读取token
|
||||
config.setIsV(true); // 是否在初始化配置时打印版本字符画
|
||||
return config;
|
||||
}
|
||||
@ -48,16 +50,18 @@
|
||||
spring:
|
||||
# sa-token配置
|
||||
sa-token:
|
||||
# token名称(同时也是cookie名称)
|
||||
# token名称 (同时也是cookie名称)
|
||||
token-name: satoken
|
||||
# token有效期,单位s 默认30天
|
||||
timeout: 2592000
|
||||
# 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
|
||||
# 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
is-share: true
|
||||
# 是否在cookie读取不到token时,继续从请求header里继续尝试读取
|
||||
is-read-head: true
|
||||
# 是否在header读取不到token时,继续从请求题参数里继续尝试读取
|
||||
# 是否尝试从请求体里读取token
|
||||
is-read-body: true
|
||||
# 是否尝试从header里读取token
|
||||
is-read-head: true
|
||||
# 是否尝试从cookie里读取token
|
||||
is-read-cookie: true
|
||||
# 是否在初始化配置时打印版本字符画
|
||||
is-v: true
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 持久层扩展
|
||||
---
|
||||
- 每次重启项目就得重新登录一遍,我想把登录数据都放在redis里,这样重启项目也不用重新登录,行不行?
|
||||
- 每次重启项目就得重新登录一遍,我想把登录数据都放在`redis`里,这样重启项目也不用重新登录,行不行?
|
||||
- 行!
|
||||
- 你需要做的就是重写`sa-token`的dao层实现方式,参考以下方案:
|
||||
|
||||
|
@ -32,7 +32,7 @@ public class StpInterfaceImpl implements StpInterface {
|
||||
|
||||
// 返回一个账号所拥有的权限码集合
|
||||
@Override
|
||||
public List<Object> getPermissionCodeList(Object login_id, String login_key) {
|
||||
public List<Object> getPermissionCodeList(Object loginId, String loginKey) {
|
||||
List<Object> list = new ArrayList<Object>(); // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
|
||||
list.add("101");
|
||||
list.add("user-add");
|
||||
|
@ -4,12 +4,12 @@
|
||||
|
||||
## 核心思想
|
||||
|
||||
- 所谓踢人下线,核心操作就是找到其指定login_id的token,并设置其失效
|
||||
- 所谓踢人下线,核心操作就是找到其指定`loginId`的token,并设置其失效
|
||||
|
||||
|
||||
## 具体API
|
||||
|
||||
#### StpUtil.logoutByLoginId(Object login_id)
|
||||
- 让指定login_id的会话注销登录(踢人下线)
|
||||
#### StpUtil.logoutByLoginId(Object loginId)
|
||||
- 让指定loginId的会话注销登录(踢人下线)
|
||||
|
||||
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
## 具体API
|
||||
|
||||
#### StpUtil.setLoginId(Object login_id)
|
||||
#### StpUtil.setLoginId(Object loginId)
|
||||
- 标记当前会话登录的账号id
|
||||
- 建议的参数类型:long | int | String, 不可以传入复杂类型,如:User、Admin等等
|
||||
- 建议的参数类型:`long | int | String`, 不可以传入复杂类型,如:`User`、`Admin`等等
|
||||
|
||||
#### StpUtil.logout()
|
||||
- 当前会话注销登录
|
||||
@ -29,12 +29,12 @@
|
||||
#### StpUtil.getLoginId()
|
||||
- 获取当前会话登录id, 如果未登录,则抛出异常:`NotLoginException`
|
||||
- 类似API还有:
|
||||
- `StpUtil.getLoginId_asString()` 获取当前会话登录id, 并转化为String类型
|
||||
- `StpUtil.getLoginId_asInt()` 获取当前会话登录id, 并转化为int类型
|
||||
- `StpUtil.getLoginId_asLong()` 获取当前会话登录id, 并转化为long类型
|
||||
- `StpUtil.getLoginIdAsString()` 获取当前会话登录id, 并转化为`String`类型
|
||||
- `StpUtil.getLoginIdAsInt()` 获取当前会话登录id, 并转化为`int`类型
|
||||
- `StpUtil.getLoginIdAsLong()` 获取当前会话登录id, 并转化为`long`类型
|
||||
|
||||
#### StpUtil.getLoginId(T default_value)
|
||||
- 获取当前会话登录id, 如果未登录,则返回默认值 (default_value可以为任意类型)
|
||||
#### StpUtil.getLoginId(T defaultValue)
|
||||
- 获取当前会话登录id, 如果未登录,则返回默认值 (`defaultValue`可以为任意类型)
|
||||
- 类似API还有:
|
||||
- `StpUtil.getLoginId_defaultNull()` 获取当前会话登录id, 如果未登录,则返回null
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
---
|
||||
|
||||
## 问题
|
||||
- 有的时候在一个项目中,我们会设计两套账号体系,比如一个商城的user表和admin表
|
||||
- 有的时候在一个项目中,我们会设计两套账号体系,比如一个商城的`user表`和`admin表`
|
||||
- 这时候,我们就需要将两套账号的权限认证分开,防止冲突
|
||||
|
||||
|
||||
@ -12,16 +12,16 @@
|
||||
- 就会发现,此类并没有任何代码逻辑,唯一做的事就是对成员变量`stpLogic`的各个API进行包装一下进行转发
|
||||
- 这样做有两个优点
|
||||
- `StpLogic`类的所有函数都可以被重写,按需扩展
|
||||
- 在构造方法时随意传入一个不同的 `login_key`,就可以再造一套账号登录体系
|
||||
- 在构造方法时随意传入一个不同的 `loginKey`,就可以再造一套账号登录体系
|
||||
|
||||
## 操作示例
|
||||
比如说,对于`StpUtil`类,我们只做`admin账号`权限验证,而对于`user账号`,我们则:
|
||||
1. 新建一个新的权限验证类,比如: `StpUserUtil.java`
|
||||
2. 将`StpUtil.java`类的全部代码复制粘贴到 `StpUserUtil.java`里
|
||||
3. 更改一下其 `login_key`, 比如:
|
||||
3. 更改一下其 `loginKey`, 比如:
|
||||
```
|
||||
// 底层的 StpLogic 对象
|
||||
public static StpLogic stpLogic = new StpLogic("user"); // login_key改为user
|
||||
public static StpLogic stpLogic = new StpLogic("user"); // loginKey改为user
|
||||
```
|
||||
4. 接下来就可以像调用`StpUtil.java`一样调用 `StpUserUtil.java`了,这两套账号认证的逻辑是完全隔离的
|
||||
|
||||
|
@ -2,23 +2,25 @@
|
||||
---
|
||||
|
||||
- 以上介绍的api都是操作当前账号,对当前账号进行各种鉴权操作,你可能会问,我能不能对别的账号进行一些操作?
|
||||
- 比如:查看账号10001有无某个权限码、获取id账号为10002的用户session,等等...
|
||||
- 比如:查看账号`10001`有无某个权限码、获取id账号为`10002`的用户`session`,等等...
|
||||
- `sa-token`在api设计时充分考虑了这一点,暴露出多个api进行此类操作
|
||||
|
||||
|
||||
## 有关操作其它账号的api
|
||||
|
||||
#### StpUtil.getTokenValueByLoginId(Object login_id)
|
||||
- 获取指定login_id的tokenValue值
|
||||
#### StpUtil.getTokenValueByLoginId(Object loginId)
|
||||
- 获取指定`loginId`的`tokenValue`值
|
||||
|
||||
#### StpUtil.logoutByLoginId(Object login_id)
|
||||
- 指定login_id的会话注销登录(踢人下线)
|
||||
#### StpUtil.logoutByLoginId(Object loginId)
|
||||
- 指定`loginId`的会话注销登录(踢人下线)
|
||||
|
||||
#### StpUtil.getSessionByLoginId(Object login_id)
|
||||
- 获取指定login_id的session
|
||||
#### StpUtil.getSessionByLoginId(Object loginId)
|
||||
- 获取指定`loginId`的`session`(如果此id尚未创建`session`, 则返回`null`)
|
||||
- 类似API还有:
|
||||
- `StpUtil.getSessionByLoginId(Object loginId, boolean isCreate)` 获取当前会话登录id, `isCreate`代表指定是否在无`session`的情况下新建并返回
|
||||
|
||||
#### StpUtil.hasPermission(Object login_id, Object pcode)
|
||||
- 指定login_id是否含有指定权限
|
||||
#### StpUtil.hasPermission(Object loginId, Object pcode)
|
||||
- 指定`loginId`是否含有指定权限
|
||||
|
||||
|
||||
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
## 何为无cookie
|
||||
|
||||
- 常规PC端鉴权方法,一般由cookie进行
|
||||
- 而cookie有两个特性:1、可由后端控制写入,2、每次请求自动提交
|
||||
- 常规PC端鉴权方法,一般由`cookie`进行
|
||||
- 而`cookie`有两个特性:1、可由后端控制写入,2、每次请求自动提交
|
||||
- 这就使得大多数web前端码农,无需任何特殊操作,就能完成鉴权的流程(因为整个流程都是后端控制完成的)
|
||||
- 而在app、小程序等前后台分离场景中,是没有cookie这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊
|
||||
- 而在app、小程序等前后台分离场景中,是没有`cookie`这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊
|
||||
- 其实很简单
|
||||
- 不能后端控制写入了,就前端自己写入(难点在**如何将token传递到前端**)
|
||||
- 每次请求不能自动提交了,那就手动提交(难点在前端如何**将token传递到后端**,同时后端**将其读取出来**)
|
||||
@ -14,14 +14,14 @@
|
||||
|
||||
## 将token传递到前端
|
||||
|
||||
1. 首先调用 `StpUtil.setLoginId(Object login_id)` 进行登录
|
||||
1. 首先调用 `StpUtil.setLoginId(Object loginId)` 进行登录
|
||||
2. 调用 `StpUtil.getTokenInfo()` 返回当前会话的token值
|
||||
- 此方法返回一个Map,有两个key:tokenName和tokenValue(token的名称和token的值)
|
||||
- 此方法返回一个Map,有两个key:`tokenName`和`tokenValue`(`token`的名称和`token`的值)
|
||||
- 将此Map传递到前台,让前端人员将这两个值保存到本地
|
||||
|
||||
## 前端将token提交到后端
|
||||
1. 无论是app还是小程序,其传递方式都大同小异
|
||||
2. 那就是,将token塞到请求header里 ,格式为:`{tokenName: tokenValue}`
|
||||
2. 那就是,将`token`塞到请求`header`里 ,格式为:`{tokenName: tokenValue}`
|
||||
3. 以经典跨端框架`uni-app`为例:
|
||||
|
||||
**方式1,简单粗暴**
|
||||
@ -71,13 +71,13 @@
|
||||
});
|
||||
```
|
||||
|
||||
4. 只要按照如此方法将token值传递到后端,`sa-token`就能像传统PC端一样自动读取到token值,进行鉴权
|
||||
5. 你可能会有疑问,难道我每个ajax都要写这么一坨?岂不是麻烦死了
|
||||
- 你当然不能每个ajax都写这么一坨,因为这种重复代码都是要封装在一个函数里统一调用的
|
||||
4. 只要按照如此方法将`token`值传递到后端,`sa-token`就能像传统PC端一样自动读取到`token`值,进行鉴权
|
||||
5. 你可能会有疑问,难道我每个`ajax`都要写这么一坨?岂不是麻烦死了
|
||||
- 你当然不能每个`ajax`都写这么一坨,因为这种重复代码都是要封装在一个函数里统一调用的
|
||||
|
||||
|
||||
## 其它解决方案?
|
||||
- 如果你对cookie非常了解,那你就会明白,所谓cookie,本质上就是一个特殊的header参数而已,
|
||||
- 而既然它只是一个header参数,我们就能就能手动模拟实现它,从而完成鉴权操作
|
||||
- 这其实是对无cookie模式的另一种解决方案,有兴趣的同学可以百度了解一下,在此暂不赘述
|
||||
- 如果你对`cookie`非常了解,那你就会明白,所谓`cookie`,本质上就是一个特殊的`header`参数而已,
|
||||
- 而既然它只是一个`header`参数,我们就能就能手动模拟实现它,从而完成鉴权操作
|
||||
- 这其实是对无`cookie`模式的另一种解决方案,有兴趣的同学可以百度了解一下,在此暂不赘述
|
||||
|
||||
|
@ -3,35 +3,35 @@
|
||||
|
||||
|
||||
## 账号session
|
||||
账号session指的是为每个登录账号分配的session
|
||||
账号`session`指的是为每个登录账号分配的`session`
|
||||
|
||||
#### StpUtil.getSession()
|
||||
- 返回当前登录账号的session(必须是登录后才能调用)
|
||||
- 返回当前登录账号的`session`(必须是登录后才能调用)
|
||||
|
||||
|
||||
## 自定义session
|
||||
自定义session指的是未登录状态下,以一个特定的值作为key,来分配的session
|
||||
自定义`session`指的是未登录状态下,以一个特定的值作为key,来分配的`session`
|
||||
|
||||
#### SaSessionCustomUtil.isExists(String sessionId)
|
||||
- 查询指定key的session,是否存在
|
||||
- 查询指定key的`session`,是否存在
|
||||
|
||||
#### SaSessionCustomUtil.getSessionById(String sessionId)
|
||||
- 获取指定key的session,如果没有,则新建并返回
|
||||
- 获取指定key的`session`,如果没有,则新建并返回
|
||||
|
||||
#### SaSessionCustomUtil.delSessionById(String sessionId)
|
||||
- 删除指定key的session
|
||||
- 删除指定key的`session`
|
||||
|
||||
|
||||
## session相关操作
|
||||
那么获取到的`SaSession`具体有哪些方法可供操作?
|
||||
|
||||
#### getId()
|
||||
- 返回此session的id
|
||||
- 返回此`session`的id
|
||||
|
||||
#### setAttribute(String key, Object value)
|
||||
- 在此session对象上写入值
|
||||
- 在此`session`对象上写入值
|
||||
|
||||
#### getAttribute(String key)
|
||||
- 在此session对象上查询值
|
||||
- 在此`session`对象上查询值
|
||||
|
||||
具体可参考`javax.servlet.http.HttpSession`,`SaSession`所含方法与其大体类似
|
@ -42,7 +42,7 @@
|
||||
<!-- 内容部分 -->
|
||||
<div class="main-box">
|
||||
<div class="content-box">
|
||||
<h1>sa-token<small>v1.0.3</small></h1>
|
||||
<h1>sa-token<small>v1.4.0</small></h1>
|
||||
<div class="sub-title">一个JavaWeb权限认证框架,强大、简单、好用</div>
|
||||
<!-- <p>0配置开箱即用,低学习成本</p> -->
|
||||
<p>登录验证、权限验证、自定义session会话、踢人下线、持久层扩展、无cookie模式、模拟他人账号、多账号体系、注解式鉴权、Spring集成...</p>
|
||||
@ -60,7 +60,7 @@
|
||||
<p>
|
||||
<span class="copyright">Copyright © 2020 </span>
|
||||
<a href="http://www.miitbeian.gov.cn/" target="_blank">鲁ICP备18046274号-2</a>
|
||||
QQ交流群:<a href="https://jq.qq.com/?_wv=1027&k=5DHN5Ib" target="_blank">784013340</a>
|
||||
QQ交流群:<a href="https://jq.qq.com/?_wv=1027&k=5DHN5Ib" target="_blank">782974737</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user