tokenSignList = session.getTokenSignList();
+ for (TokenSign tokenSign : tokenSignList) {
+ // 1. 获取token
+ String tokenValue = tokenSign.getValue();
+ // 2. 清理掉[token-最后操作时间]
+ clearLastActivity(tokenValue);
+ // 3. 标记:已被踢下线
+ SaTokenManager.getSaTokenDao().updateValue(getKeyTokenValue(tokenValue), NotLoginException.KICK_OUT); // 标记:已被踢下线
+ // 4. 清理账号session上的token签名
+ session.removeTokenSign(tokenValue);
+ }
+ // 尝试注销session
+ session.logoutByTokenSignCountToZero();
}
- /**
- * 指定loginId的会话注销登录(踢人下线)
- * @param loginId 账号id
- */
- public void kickoutByLoginId(Object loginId) {
-
- // 获取相应tokenValue
- String tokenValue = getTokenValueByLoginId(loginId);
- if(tokenValue == null) {
- return;
- }
-
- // 清除相关数据
- SaTokenManager.getSaTokenDao().updateValue(getKeyTokenValue(tokenValue), NotLoginException.KICK_OUT); // 标记:已被踢下线
- SaTokenManager.getSaTokenDao().deleteKey(getKeyLoginId(loginId)); // 清除id-token键值对
- SaTokenManager.getSaTokenDao().deleteSession(getKeySession(loginId)); // 清除其session
- clearLastActivity(tokenValue); // 同时清理掉 [最后操作时间]
- }
// 查询相关
@@ -454,7 +484,6 @@ public class StpLogic {
/**
* 获取当前token的专属-session,如果session尚未创建,isCreate代表是否新建并返回
- * 只有当前会话属于登录状态才可调用
* @param isCreate 是否新建
* @return session会话
*/
@@ -474,8 +503,7 @@ public class StpLogic {
}
/**
- * 获取当前token的专属-session,如果session尚未创建,则新建并返回
- *
只有当前会话属于登录状态才可调用
+ * 获取当前token的专属-session,如果session尚未创建,则新建并返回
* @return session会话
*/
public SaSession getTokenSession() {
@@ -510,7 +538,7 @@ public class StpLogic {
// 删除[最后操作时间]
SaTokenManager.getSaTokenDao().deleteKey(getKeyLastActivityTime(tokenValue));
// 清除标记
- SaTokenManager.getSaTokenServlet().getRequest().removeAttribute(SaTokenInsideUtil.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY);
+ SaTokenManager.getSaTokenServlet().getRequest().removeAttribute(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY);
}
/**
@@ -524,7 +552,7 @@ public class StpLogic {
}
// 如果本次请求已经有了[检查标记], 则立即返回
HttpServletRequest request = SaTokenManager.getSaTokenServlet().getRequest();
- if(request.getAttribute(SaTokenInsideUtil.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY) != null) {
+ if(request.getAttribute(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY) != null) {
return;
}
// ------------ 验证是否已经 [临时过期]
@@ -541,7 +569,7 @@ public class StpLogic {
// --- 至此,验证已通过
// 打上[检查标记],标记一下当前请求已经通过验证,避免一次请求多次验证,造成不必要的性能消耗
- request.setAttribute(SaTokenInsideUtil.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true);
+ request.setAttribute(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true);
}
/**
@@ -795,7 +823,43 @@ public class StpLogic {
throw new NotPermissionException(permissionArray[0], this.loginKey); // 没有权限抛出异常
}
}
-
+
+
+ // =================== id 反查token 相关操作 ===================
+
+
+ /**
+ * 获取指定loginId的tokenValue
+ *
在配置为允许并发登录时,此方法只会返回队列的最后一个token,
+ * 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
+ * @param loginId 账号id
+ * @return token值
+ */
+ public String getTokenValueByLoginId(Object loginId) {
+ List tokenValueList = getTokenValueListByLoginId(loginId);
+ return tokenValueList.size() == 0 ? null : tokenValueList.get(tokenValueList.size() - 1);
+ }
+
+ /**
+ * 获取指定loginId的tokenValue
+ * @param loginId 账号id
+ * @return 此loginId的所有相关token
+ */
+ public List getTokenValueListByLoginId(Object loginId) {
+ // 如果session为null的话直接返回空集合
+ SaSession session = getSessionByLoginId(loginId, false);
+ if(session == null) {
+ return Arrays.asList();
+ }
+ // 遍历解析
+ List tokenSignList = session.getTokenSignList();
+ List tokenValueList = new ArrayList<>();
+ for (TokenSign tokenSign : tokenSignList) {
+ tokenValueList.add(tokenSign.getValue());
+ }
+ return tokenValueList;
+ }
+
// =================== 返回相应key ===================
@@ -807,21 +871,13 @@ public class StpLogic {
return getConfig().getTokenName();
}
/**
- * 获取key: tokenValue 持久化
+ * 获取key: tokenValue 持久化 token-id
* @param tokenValue token值
* @return key
*/
public String getKeyTokenValue(String tokenValue) {
return getConfig().getTokenName() + ":" + loginKey + ":token:" + tokenValue;
}
- /**
- * 获取key: id 持久化
- * @param loginId 账号id
- * @return key
- */
- public String getKeyLoginId(Object loginId) {
- return getConfig().getTokenName() + ":" + loginKey + ":id:" + loginId;
- }
/**
* 获取key: session 持久化
* @param loginId 账号id
@@ -846,9 +902,13 @@ public class StpLogic {
public String getKeyLastActivityTime(String tokenValue) {
return getConfig().getTokenName() + ":" + loginKey + ":last-activity:" + tokenValue;
}
-
+
+
+ // =================== Bean对象代理 ===================
+
/**
* 返回配置对象
+ * @return 配置对象
*/
public SaTokenConfig getConfig() {
// 为什么再次代理一层? 为某些极端业务场景下[需要不同StpLogic不同配置]提供便利
@@ -856,4 +916,8 @@ public class StpLogic {
}
+
+
+
+
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java
index 23b6c09c..2d98ec82 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java
@@ -1,5 +1,7 @@
package cn.dev33.satoken.stp;
+import java.util.List;
+
import cn.dev33.satoken.session.SaSession;
/**
@@ -32,15 +34,6 @@ public class StpUtil {
return stpLogic.getTokenValue();
}
- /**
- * 获取指定loginId的tokenValue
- * @param loginId 账号id
- * @return token值
- */
- public static String getTokenValueByLoginId(Object loginId) {
- return stpLogic.getTokenValueByLoginId(loginId);
- }
-
/**
* 获取当前StpLogin的loginKey
* @return 当前StpLogin的loginKey
@@ -76,20 +69,22 @@ public class StpUtil {
}
/**
- * 指定loginId的会话注销登录(正常注销下线)
+ * 指定token的会话注销登录
+ * @param tokenValue 指定token
+ */
+ public static void logoutByTokenValue(String tokenValue) {
+ stpLogic.logoutByTokenValue(tokenValue);
+ }
+
+ /**
+ * 指定loginId的会话注销登录(踢人下线)
+ * 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
* @param loginId 账号id
*/
public static void logoutByLoginId(Object loginId) {
stpLogic.logoutByLoginId(loginId);
}
- /**
- * 指定loginId的会话注销登录(踢人下线)
- * @param loginId 账号id
- */
- public static void kickoutByLoginId(Object loginId) {
- stpLogic.kickoutByLoginId(loginId);
- }
// 查询相关
@@ -181,10 +176,9 @@ public class StpUtil {
}
/**
- * 获取指定loginId的session, 如果session尚未创建,isCreate=是否新建并返回
- * @param loginId 账号id
- * @param isCreate 是否新建
- * @return SaSession
+ * 获取指定loginId的session,如果session尚未创建,则新建并返回
+ * @param loginId 账号id
+ * @return session会话
*/
public static SaSession getSessionByLoginId(Object loginId) {
return stpLogic.getSessionByLoginId(loginId);
@@ -221,7 +215,6 @@ public class StpUtil {
/**
* 获取当前token的专属-session,如果session尚未创建,则新建并返回
- *
只有当前会话属于登录状态才可调用
* @return session会话
*/
public static SaSession getTokenSession() {
@@ -376,4 +369,27 @@ public class StpUtil {
}
+ // =================== id 反查token 相关操作 ===================
+
+ /**
+ * 获取指定loginId的tokenValue
+ *
在配置为允许并发登录时,此方法只会返回队列的最后一个token,
+ * 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
+ * @param loginId 账号id
+ * @return token值
+ */
+ public static String getTokenValueByLoginId(Object loginId) {
+ return stpLogic.getTokenValueByLoginId(loginId);
+ }
+
+ /**
+ * 获取指定loginId的tokenValue
+ * @param loginId 账号id
+ * @return 此loginId的所有相关token
+ */
+ public static List getTokenValueListByLoginId(Object loginId) {
+ return stpLogic.getTokenValueListByLoginId(loginId);
+ }
+
+
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java
new file mode 100644
index 00000000..10e8decd
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java
@@ -0,0 +1,45 @@
+package cn.dev33.satoken.util;
+
+/**
+ * 定义sa-token的所有常量
+ * @author kong
+ *
+ */
+public class SaTokenConsts {
+
+ /**
+ * sa-token 版本号
+ */
+ public static final String VERSION_NO = "v1.8.0";
+
+ /**
+ * sa-token 开源地址
+ */
+ public static final String GITHUB_URL = "https://github.com/click33/sa-token";
+
+ /**
+ * 如果token为本次请求新创建的,则以此字符串为key存储在当前request中 JUST_CREATED_SAVE_KEY
+ */
+ public static final String JUST_CREATED_SAVE_KEY = "JUST_CREATED_SAVE_KEY_";
+
+ /**
+ * 如果本次请求已经验证过[无操作过期], 则以此值存储在当前request中 TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY
+ */
+ public static final String TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY = "TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY_";
+
+ /**
+ * 在登录时,默认使用的设备名称
+ */
+ public static final String DEFAULT_LOGIN_DEVICE = "default-device";
+
+// /**
+// * 在用一个字符串存储多个token时,所使用的分隔符
+// */
+// public static final String MULTIPLE_TOKEN_SEPARATOR = ",";
+
+
+
+
+
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenInsideUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenInsideUtil.java
index b85c16f1..483a3422 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenInsideUtil.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenInsideUtil.java
@@ -10,16 +10,6 @@ import java.util.Random;
public class SaTokenInsideUtil {
- /**
- * sa-token 版本号
- */
- public static final String VERSION_NO = "v1.7.0";
-
- /**
- * sa-token 开源地址
- */
- public static final String GITHUB_URL = "https://github.com/click33/sa-token";
-
/**
* 打印 sa-token 版本字符画
*/
@@ -28,20 +18,11 @@ public class SaTokenInsideUtil {
"____ ____ ___ ____ _ _ ____ _ _ \r\n" +
"[__ |__| __ | | | |_/ |___ |\\ | \r\n" +
"___] | | | |__| | \\_ |___ | \\| \r\n" +
- "sa-token:" + VERSION_NO + " \r\n" +
- "GitHub:" + GITHUB_URL; // + "\r\n";
+ "sa-token:" + SaTokenConsts.VERSION_NO + " \r\n" +
+ "GitHub:" + SaTokenConsts.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_";
-
- /**
- * 如果本次请求已经验证过[无操作过期], 则以此值存储在当前request中 TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY
- */
- public static final String TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY = "TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY_";
/**
* 生成指定长度的随机字符串
@@ -61,6 +42,7 @@ public class SaTokenInsideUtil {
/**
* 以当前时间戳和随机int数字拼接一个随机字符串
+ * @return 随机字符串
*/
public static String getMarking28() {
return System.currentTimeMillis() + "" + new Random().nextInt(Integer.MAX_VALUE);
diff --git a/sa-token-dao-redis-jackson/.gitignore b/sa-token-dao-redis-jackson/.gitignore
new file mode 100644
index 00000000..f56feec7
--- /dev/null
+++ b/sa-token-dao-redis-jackson/.gitignore
@@ -0,0 +1,12 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.factorypath
+
+.idea/
\ No newline at end of file
diff --git a/sa-token-dao-redis-jackson/pom.xml b/sa-token-dao-redis-jackson/pom.xml
new file mode 100644
index 00000000..293c235a
--- /dev/null
+++ b/sa-token-dao-redis-jackson/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+
+ cn.dev33
+ sa-token-parent
+ 1.8.0
+
+ jar
+
+ sa-token-dao-redis-jackson
+ sa-token-dao-redis-jackson
+ sa-token integrate redis (to jackson)
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot-starter
+ 1.8.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ 2.3.7.RELEASE
+
+
+
+
+
+
diff --git a/sa-token-dao-redis-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedisJackson.java b/sa-token-dao-redis-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedisJackson.java
new file mode 100644
index 00000000..e0af12ba
--- /dev/null
+++ b/sa-token-dao-redis-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedisJackson.java
@@ -0,0 +1,185 @@
+package cn.dev33.satoken.dao;
+
+import java.lang.reflect.Field;
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import cn.dev33.satoken.session.SaSession;
+
+/**
+ * sa-token持久层的实现类, 基于redis (to jackson)
+ */
+@Component
+public class SaTokenDaoRedisJackson implements SaTokenDao {
+
+ /**
+ * ObjectMapper对象 (以public作用于暴露出此对象,方便开发者二次更改配置)
+ */
+ public ObjectMapper objectMapper;
+
+ /**
+ * string专用
+ */
+ @Autowired
+ public StringRedisTemplate stringRedisTemplate;
+
+ /**
+ * SaSession专用
+ */
+ public RedisTemplate sessionRedisTemplate;
+ @Autowired
+ public void setSessionRedisTemplate(RedisConnectionFactory connectionFactory) {
+ // 指定相应的序列化方案
+ StringRedisSerializer keySerializer = new StringRedisSerializer();
+ GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer();
+ // 通过反射获取Mapper对象, 配置[忽略未知字段], 增强兼容性
+ try {
+ Field field = GenericJackson2JsonRedisSerializer.class.getDeclaredField("mapper");
+ field.setAccessible(true);
+ ObjectMapper objectMapper = (ObjectMapper) field.get(valueSerializer);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ this.objectMapper = objectMapper;
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+ // 构建RedisTemplate
+ RedisTemplate template = new RedisTemplate();
+ template.setConnectionFactory(connectionFactory);
+ template.setKeySerializer(keySerializer);
+ template.setHashKeySerializer(keySerializer);
+ template.setValueSerializer(valueSerializer);
+ template.setHashValueSerializer(valueSerializer);
+ template.afterPropertiesSet();
+ if(this.sessionRedisTemplate == null) {
+ this.sessionRedisTemplate = template;
+ }
+ }
+
+
+ /**
+ * 根据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) {
+ // 判断是否为永不过期
+ if(timeout == SaTokenDao.NEVER_EXPIRE) {
+ stringRedisTemplate.opsForValue().set(key, value);
+ } else {
+ stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * 修改指定key-value键值对 (过期时间取原来的值)
+ */
+ @Override
+ public void updateValue(String key, String value) {
+ long expire = getTimeout(key);
+ if(expire == SaTokenDao.NOT_VALUE_EXPIRE) { // -2 = 无此键
+ return;
+ }
+ this.setValue(key, value, expire);
+ }
+
+ /**
+ * 删除一个指定的key
+ */
+ @Override
+ public void deleteKey(String key) {
+ stringRedisTemplate.delete(key);
+ }
+
+ /**
+ * 根据key获取value,如果没有,则返回空
+ */
+ @Override
+ public long getTimeout(String key) {
+ return stringRedisTemplate.getExpire(key);
+ }
+
+ /**
+ * 修改指定key的剩余存活时间 (单位: 秒)
+ */
+ @Override
+ public void updateTimeout(String key, long timeout) {
+ stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
+ }
+
+
+
+ /**
+ * 根据指定key的Session,如果没有,则返回空
+ */
+ @Override
+ public SaSession getSession(String sessionId) {
+ return sessionRedisTemplate.opsForValue().get(sessionId);
+ }
+
+ /**
+ * 将指定Session持久化
+ */
+ @Override
+ public void saveSession(SaSession session, long timeout) {
+ // 判断是否为永不过期
+ if(timeout == SaTokenDao.NEVER_EXPIRE) {
+ sessionRedisTemplate.opsForValue().set(session.getId(), session);
+ } else {
+ sessionRedisTemplate.opsForValue().set(session.getId(), session, timeout, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * 更新指定session
+ */
+ @Override
+ public void updateSession(SaSession session) {
+ long expire = getSessionTimeout(session.getId());
+ if(expire == SaTokenDao.NOT_VALUE_EXPIRE) { // -2 = 无此键
+ return;
+ }
+ this.saveSession(session, expire);
+ }
+
+ /**
+ * 删除一个指定的session
+ */
+ @Override
+ public void deleteSession(String sessionId) {
+ sessionRedisTemplate.delete(sessionId);
+ }
+
+ /**
+ * 获取指定SaSession的剩余存活时间 (单位: 秒)
+ */
+ @Override
+ public long getSessionTimeout(String sessionId) {
+ return sessionRedisTemplate.getExpire(sessionId);
+ }
+
+ /**
+ * 修改指定SaSession的剩余存活时间 (单位: 秒)
+ */
+ @Override
+ public void updateSessionTimeout(String sessionId, long timeout) {
+ sessionRedisTemplate.expire(sessionId, timeout, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/sa-token-dao-redis-jackson/src/main/resources/META-INF/spring.factories b/sa-token-dao-redis-jackson/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..d792b9f9
--- /dev/null
+++ b/sa-token-dao-redis-jackson/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.dev33.satoken.dao.SaTokenDaoRedisJackson
\ No newline at end of file
diff --git a/sa-token-dao-redis/pom.xml b/sa-token-dao-redis/pom.xml
index 778e0297..9e66756a 100644
--- a/sa-token-dao-redis/pom.xml
+++ b/sa-token-dao-redis/pom.xml
@@ -7,7 +7,7 @@
cn.dev33
sa-token-parent
- 1.7.0
+ 1.8.0
jar
@@ -20,14 +20,14 @@
cn.dev33
sa-token-spring-boot-starter
- 1.7.0
+ 1.8.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ 2.3.7.RELEASE
-
-
- org.springframework.boot
- spring-boot-starter-redis
- RELEASE
-
diff --git a/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java b/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java
index a475eb93..81d5e0be 100644
--- a/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java
+++ b/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java
@@ -3,6 +3,7 @@ package cn.dev33.satoken.dao;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
@@ -21,18 +22,28 @@ public class SaTokenDaoRedis implements SaTokenDao {
* string专用
*/
@Autowired
- StringRedisTemplate stringRedisTemplate;
+ public StringRedisTemplate stringRedisTemplate;
/**
* SaSession专用
*/
- RedisTemplate redisTemplate;
+ public RedisTemplate sessionRedisTemplate;
@Autowired
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public void setRedisTemplate(RedisTemplate redisTemplate) {
- redisTemplate.setKeySerializer(new StringRedisSerializer());
- redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
- this.redisTemplate = redisTemplate;
+ public void setSessionRedisTemplate(RedisConnectionFactory connectionFactory) {
+ // 指定相应的序列化方案
+ StringRedisSerializer keySerializer = new StringRedisSerializer();
+ JdkSerializationRedisSerializer valueSerializer = new JdkSerializationRedisSerializer();
+ // 构建RedisTemplate
+ RedisTemplate template = new RedisTemplate();
+ template.setConnectionFactory(connectionFactory);
+ template.setKeySerializer(keySerializer);
+ template.setHashKeySerializer(keySerializer);
+ template.setValueSerializer(valueSerializer);
+ template.setHashValueSerializer(valueSerializer);
+ template.afterPropertiesSet();
+ if(this.sessionRedisTemplate == null) {
+ this.sessionRedisTemplate = template;
+ }
}
@@ -58,7 +69,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 根据key获取value,如果没有,则返回空
+ * 修改指定key-value键值对 (过期时间取原来的值)
*/
@Override
public void updateValue(String key, String value) {
@@ -70,7 +81,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 根据key获取value,如果没有,则返回空
+ * 删除一个指定的key
*/
@Override
public void deleteKey(String key) {
@@ -84,6 +95,15 @@ public class SaTokenDaoRedis implements SaTokenDao {
public long getTimeout(String key) {
return stringRedisTemplate.getExpire(key);
}
+
+ /**
+ * 修改指定key的剩余存活时间 (单位: 秒)
+ */
+ @Override
+ public void updateTimeout(String key, long timeout) {
+ stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
+ }
+
/**
@@ -91,7 +111,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public SaSession getSession(String sessionId) {
- return redisTemplate.opsForValue().get(sessionId);
+ return sessionRedisTemplate.opsForValue().get(sessionId);
}
/**
@@ -101,9 +121,9 @@ public class SaTokenDaoRedis implements SaTokenDao {
public void saveSession(SaSession session, long timeout) {
// 判断是否为永不过期
if(timeout == SaTokenDao.NEVER_EXPIRE) {
- redisTemplate.opsForValue().set(session.getId(), session);
+ sessionRedisTemplate.opsForValue().set(session.getId(), session);
} else {
- redisTemplate.opsForValue().set(session.getId(), session, timeout, TimeUnit.SECONDS);
+ sessionRedisTemplate.opsForValue().set(session.getId(), session, timeout, TimeUnit.SECONDS);
}
}
@@ -124,7 +144,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public void deleteSession(String sessionId) {
- redisTemplate.delete(sessionId);
+ sessionRedisTemplate.delete(sessionId);
}
/**
@@ -132,7 +152,15 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public long getSessionTimeout(String sessionId) {
- return redisTemplate.getExpire(sessionId);
+ return sessionRedisTemplate.getExpire(sessionId);
}
+ /**
+ * 修改指定SaSession的剩余存活时间 (单位: 秒)
+ */
+ @Override
+ public void updateSessionTimeout(String sessionId, long timeout) {
+ sessionRedisTemplate.expire(sessionId, timeout, TimeUnit.SECONDS);
+ }
+
}
diff --git a/sa-token-demo-springboot/pom.xml b/sa-token-demo-springboot/pom.xml
index 03008c76..bc599554 100644
--- a/sa-token-demo-springboot/pom.xml
+++ b/sa-token-demo-springboot/pom.xml
@@ -29,14 +29,27 @@
cn.dev33
sa-token-spring-boot-starter
- 1.7.0
+ 1.8.0
-
+
+
+
+
+
+
+
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 4422fe1d..61e902b8 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
@@ -7,7 +7,7 @@ import cn.dev33.satoken.SaTokenManager;
@SpringBootApplication
public class SaTokenDemoApplication {
-
+
public static void main(String[] args) {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("\n启动成功:sa-token配置如下:" + SaTokenManager.getConfig());
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
index af334cc8..c5fc7823 100644
--- 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
@@ -20,12 +20,10 @@ public class MySaTokenConfig implements WebMvcConfigurer {
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.setActivityTimeout(-1); // token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
+ config.setAllowConcurrentLogin(true); // 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
+ config.setIsShare(true); // 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
config.setTokenStyle("uuid"); // token风格
- config.setIsV(true); // 是否在初始化配置时打印版本字符画
return config;
}
diff --git a/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpUserUtil.java b/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpUserUtil.java
deleted file mode 100644
index 4311089c..00000000
--- a/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpUserUtil.java
+++ /dev/null
@@ -1,354 +0,0 @@
-package com.pj.satoken;
-
-import cn.dev33.satoken.session.SaSession;
-import cn.dev33.satoken.stp.SaTokenInfo;
-import cn.dev33.satoken.stp.StpLogic;
-
-/**
- * user认证实现
- * @author kong
- */
-public class StpUserUtil {
-
- /**
- * 底层的 StpLogic 对象
- */
- public static StpLogic stpLogic = new StpLogic("user");
-
-
- // =================== 获取token 相关 ===================
-
- /**
- * 返回token名称
- * @return 此StpLogic的token名称
- */
- public static String getTokenName() {
- return stpLogic.getTokenName();
- }
-
- /**
- * 获取当前tokenValue
- * @return 当前tokenValue
- */
- public static String getTokenValue() {
- return stpLogic.getTokenValue();
- }
-
- /**
- * 获取指定loginId的tokenValue
- * @param loginId 账号id
- * @return token值
- */
- public static String getTokenValueByLoginId(Object loginId) {
- return stpLogic.getTokenValueByLoginId(loginId);
- }
-
- /**
- * 获取当前StpLogin的loginKey
- * @return 当前StpLogin的loginKey
- */
- public static String getLoginKey(){
- return stpLogic.getLoginKey();
- }
-
- /**
- * 获取当前会话的token信息
- * @return token信息
- */
- public static SaTokenInfo getTokenInfo() {
- return stpLogic.getTokenInfo();
- }
-
-
- // =================== 登录相关操作 ===================
-
- /**
- * 在当前会话上登录id
- * @param loginId 登录id,建议的类型:(long | int | String)
- */
- public static void setLoginId(Object loginId) {
- stpLogic.setLoginId(loginId);
- }
-
- /**
- * 当前会话注销登录
- */
- public static void logout() {
- stpLogic.logout();
- }
-
- /**
- * 指定loginId的会话注销登录(正常注销下线)
- * @param loginId 账号id
- */
- public static void logoutByLoginId(Object loginId) {
- stpLogic.logoutByLoginId(loginId);
- }
-
- /**
- * 指定loginId的会话注销登录(踢人下线)
- * @param loginId 账号id
- */
- public static void kickoutByLoginId(Object loginId) {
- stpLogic.kickoutByLoginId(loginId);
- }
-
- // 查询相关
-
- /**
- * 获取当前会话是否已经登录
- * @return 是否已登录
- */
- public static boolean isLogin() {
- return stpLogic.isLogin();
- }
-
- /**
- * 检验当前会话是否已经登录,如未登录,则抛出异常
- */
- public static void checkLogin() {
- stpLogic.checkLogin();
- }
-
- /**
- * 获取当前会话账号id, 如果未登录,则抛出异常
- * @return 账号id
- */
- public static Object getLoginId() {
- return stpLogic.getLoginId();
- }
-
- /**
- * 获取当前会话登录id, 如果未登录,则返回默认值
- * @param 返回类型
- * @param defaultValue 默认值
- * @return 登录id
- */
- public static T getLoginId(T defaultValue) {
- return stpLogic.getLoginId(defaultValue);
- }
-
- /**
- * 获取当前会话登录id, 如果未登录,则返回null
- * @return 账号id
- */
- public static Object getLoginIdDefaultNull() {
- return stpLogic.getLoginIdDefaultNull();
- }
-
- /**
- * 获取当前会话登录id, 并转换为String
- * @return 账号id
- */
- public static String getLoginIdAsString() {
- return stpLogic.getLoginIdAsString();
- }
-
- /**
- * 获取当前会话登录id, 并转换为int
- * @return 账号id
- */
- public static int getLoginIdAsInt() {
- return stpLogic.getLoginIdAsInt();
- }
-
- /**
- * 获取当前会话登录id, 并转换为long
- * @return 账号id
- */
- public static long getLoginIdAsLong() {
- return stpLogic.getLoginIdAsLong();
- }
-
- /**
- * 获取指定token对应的登录id,如果未登录,则返回 null
- * @param tokenValue token
- * @return 登录id
- */
- public static Object getLoginIdByToken(String tokenValue) {
- return stpLogic.getLoginIdByToken(tokenValue);
- }
-
-
- // =================== session相关 ===================
-
- /**
- * 获取指定loginId的session, 如果session尚未创建,isCreate=是否新建并返回
- * @param loginId 账号id
- * @param isCreate 是否新建
- * @return SaSession
- */
- public static SaSession getSessionByLoginId(Object loginId, boolean isCreate) {
- return stpLogic.getSessionByLoginId(loginId, isCreate);
- }
-
- /**
- * 获取指定loginId的session, 如果session尚未创建,isCreate=是否新建并返回
- * @param loginId 账号id
- * @param isCreate 是否新建
- * @return SaSession
- */
- public static SaSession getSessionByLoginId(Object loginId) {
- return stpLogic.getSessionByLoginId(loginId);
- }
-
- /**
- * 获取当前会话的session, 如果session尚未创建,isCreate=是否新建并返回
- * @param isCreate 是否新建
- * @return 当前会话的session
- */
- public static SaSession getSession(boolean isCreate) {
- return stpLogic.getSession(isCreate);
- }
-
- /**
- * 获取当前会话的session,如果session尚未创建,则新建并返回
- * @return 当前会话的session
- */
- public static SaSession getSession() {
- return stpLogic.getSession();
- }
-
-
- // =================== token专属session ===================
-
- /**
- * 获取指定token的专属session,如果session尚未创建,则新建并返回
- * @param tokenValue token值
- * @return session会话
- */
- public static SaSession getTokenSessionByToken(String tokenValue) {
- return stpLogic.getTokenSessionByToken(tokenValue);
- }
-
- /**
- * 获取当前token的专属-session,如果session尚未创建,则新建并返回
- * 只有当前会话属于登录状态才可调用
- * @return session会话
- */
- public static SaSession getTokenSession() {
- return stpLogic.getTokenSession();
- }
-
-
- // =================== [临时过期] 验证相关 ===================
-
- /**
- * 检查当前token 是否已经[临时过期],如果已经过期则抛出异常
- */
- public static void checkActivityTimeout() {
- stpLogic.checkActivityTimeout();
- }
-
- /**
- * 续签当前token:(将 [最后操作时间] 更新为当前时间戳)
- *
请注意: 即时token已经 [临时过期] 也可续签成功,
- * 如果此场景下需要提示续签失败,可在此之前调用 checkActivityTimeout() 强制检查是否过期即可
- */
- public static void updateLastActivityToNow() {
- stpLogic.updateLastActivityToNow();
- }
-
-
- // =================== 过期时间相关 ===================
-
- /**
- * 获取当前登录者的token剩余有效时间 (单位: 秒)
- * @return token剩余有效时间
- */
- public static long getTimeout() {
- return stpLogic.getTokenTimeout();
- }
-
- /**
- * 获取指定loginId的token剩余有效时间 (单位: 秒)
- * @param loginId 指定loginId
- * @return token剩余有效时间
- */
- public static long getTimeoutByLoginId(Object loginId) {
- return stpLogic.getTokenTimeoutByLoginId(loginId);
- }
-
- /**
- * 获取当前登录者的Session剩余有效时间 (单位: 秒)
- * @return token剩余有效时间
- */
- public static long getSessionTimeout() {
- return stpLogic.getSessionTimeout();
- }
-
- /**
- * 获取指定loginId的Session剩余有效时间 (单位: 秒)
- * @param loginId 指定loginId
- * @return token剩余有效时间
- */
- public static long getSessionTimeoutByLoginId(Object loginId) {
- return stpLogic.getSessionTimeoutByLoginId(loginId);
- }
-
- /**
- * 获取当前token[临时过期]剩余有效时间 (单位: 秒)
- * @return token[临时过期]剩余有效时间
- */
- public static long getTokenActivityTimeout() {
- return stpLogic.getTokenActivityTimeout();
- }
-
- /**
- * 获取指定token[临时过期]剩余有效时间 (单位: 秒)
- * @param tokenValue 指定token
- * @return token[临时过期]剩余有效时间
- */
- public static long getTokenActivityTimeoutByToken(String tokenValue) {
- return stpLogic.getTokenActivityTimeoutByToken(tokenValue);
- }
-
-
-
- // =================== 权限验证操作 ===================
-
- /**
- * 指定账号id是否含有指定权限
- * @param loginId 账号id
- * @param permissionCode 权限码
- * @return 是否含有指定权限
- */
- public static boolean hasPermission(Object loginId, String permissionCode) {
- return stpLogic.hasPermission(loginId, permissionCode);
- }
-
- /**
- * 当前账号id是否含有指定权限
- * @param permissionCode 权限码
- * @return 是否含有指定权限
- */
- public static boolean hasPermission(String permissionCode) {
- return stpLogic.hasPermission(permissionCode);
- }
-
- /**
- * 当前账号是否含有指定权限, 没有就抛出异常
- * @param permissionCode 权限码
- */
- public static void checkPermission(String permissionCode) {
- stpLogic.checkPermission(permissionCode);
- }
-
- /**
- * 当前账号是否含有指定权限, [指定多个,必须全都有]
- * @param permissionCodeArray 权限码数组
- */
- public static void checkPermissionAnd(String... permissionCodeArray) {
- stpLogic.checkPermissionAnd(permissionCodeArray);
- }
-
- /**
- * 当前账号是否含有指定权限, [指定多个,有一个就可以通过]
- * @param permissionCodeArray 权限码数组
- */
- public static void checkPermissionOr(String... permissionCodeArray) {
- stpLogic.checkPermissionOr(permissionCodeArray);
- }
-
-
-}
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 661fe6b2..096ac1c4 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
@@ -1,11 +1,17 @@
package com.pj.test;
+import java.util.Date;
+
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
@@ -27,22 +33,22 @@ public class TestController {
System.out.println("当前会话的token:" + StpUtil.getTokenValue());
System.out.println("当前是否登录:" + StpUtil.isLogin());
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.getLoginIdAsInt()); // 获取登录id并转为int
+// System.out.println("当前token信息:" + StpUtil.getTokenInfo());
-// StpUtil.logout();
-// System.out.println("注销登录");
-// System.out.println("当前是否登录:" + StpUtil.isLogin());
-// 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.getLoginIdDefaultNull());
-
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试退出登录 , 浏览器访问: http://localhost:8081/test/logout
+ @RequestMapping("logout")
+ public AjaxJson logout() {
+ StpUtil.logout();
+// StpUtil.logoutByLoginId(10001);
return AjaxJson.getSuccess();
}
@@ -91,17 +97,17 @@ public class TestController {
return AjaxJson.getSuccess();
}
-
// 测试会话session接口, 浏览器访问: http://localhost:8081/test/session
@RequestMapping("session")
- public AjaxJson session() {
+ public AjaxJson session() throws JsonProcessingException {
System.out.println("======================= 进入方法,测试会话session接口 ========================= ");
System.out.println("当前是否登录:" + StpUtil.isLogin());
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
System.out.println("测试取值name:" + StpUtil.getSession().getAttribute("name"));
- StpUtil.getSession().setAttribute("name", "张三"); // 写入一个值
+ StpUtil.getSession().setAttribute("name", new Date()); // 写入一个值
System.out.println("测试取值name:" + StpUtil.getSession().getAttribute("name"));
+ System.out.println( new ObjectMapper().writeValueAsString(StpUtil.getSession()));
return AjaxJson.getSuccess();
}
@@ -155,10 +161,10 @@ public class TestController {
return AjaxJson.getSuccess();
}
- // 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/atLogin
- @SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
- @RequestMapping("atLogin")
- public AjaxJson atLogin() {
+ // 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/atJurOr
+ @RequestMapping("atJurOr")
+ @SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR) // 注解式鉴权:只要具有其中一个权限即可通过校验
+ public AjaxJson atJurOr() {
return AjaxJson.getSuccessData("用户信息");
}
@@ -175,10 +181,8 @@ public class TestController {
public AjaxJson kickOut() {
// 先登录上
StpUtil.setLoginId(10001);
- // 清退下线
-// StpUtil.logoutByLoginId(10001);
// 踢下线
- StpUtil.kickoutByLoginId(10001);
+ StpUtil.logoutByLoginId(10001);
// 再尝试获取
StpUtil.getLoginId();
// 返回
@@ -188,15 +192,7 @@ public class TestController {
// 测试 浏览器访问: http://localhost:8081/test/test
@RequestMapping("test")
public AjaxJson test() {
- StpUtil.setLoginId(10001);
-// StpUtil.getSession();
- StpUtil.logout();
-
-// System.out.println(StpUtil.getSession().getId());
-// System.out.println(StpUserUtil.getSession().getId());
-// StpUtil.getSessionByLoginId(10001).setAttribute("name", "123");
-// System.out.println(StpUtil.getSessionByLoginId(10001).getAttribute("name"));
-
+ StpUtil.getTokenSession().logout();
return AjaxJson.getSuccess();
}
diff --git a/sa-token-demo-springboot/src/main/resources/application.yml b/sa-token-demo-springboot/src/main/resources/application.yml
index 97f4bb9b..118661fb 100644
--- a/sa-token-demo-springboot/src/main/resources/application.yml
+++ b/sa-token-demo-springboot/src/main/resources/application.yml
@@ -9,21 +9,14 @@ spring:
token-name: satoken
# token有效期,单位s 默认30天, -1代表永不过期
timeout: 2592000
- # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒, 默认-1 代表不限制 (例如可以设置为1800代表30分钟内无操作就过期)
+ # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
- # 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
+ # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
+ allow-concurrent-login: true
+ # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: true
- # 是否尝试从请求体里读取token
- is-read-body: true
- # 是否尝试从header里读取token
- is-read-head: true
- # 是否尝试从cookie里读取token
- is-read-cookie: true
# token风格
token-style: uuid
- # 是否在初始化配置时打印版本字符画
- is-v: true
- tokenSessionCheckLogin: false
# redis配置
diff --git a/sa-token-doc/doc/README.md b/sa-token-doc/doc/README.md
index a497595e..c30805e6 100644
--- a/sa-token-doc/doc/README.md
+++ b/sa-token-doc/doc/README.md
@@ -1,11 +1,11 @@
-sa-token v1.7.0
+sa-token v1.8.0
一个JavaWeb轻量级权限认证框架,功能全面,上手简单
-
+
@@ -17,28 +17,29 @@
## 😘 在线资料
-- ##### [官网首页:http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
-- ##### [在线文档:http://sa-token.dev33.cn/doc/index.html](http://sa-token.dev33.cn/doc/index.html)
-- ##### [需求提交:我们深知一个优秀的项目需要海纳百川,点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
-- ##### [开源不易,求鼓励,点个star吧](https://github.com/click33/sa-token)
+
+- [官网首页:http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
+
+- [在线文档:http://sa-token.dev33.cn/doc/index.html](http://sa-token.dev33.cn/doc/index.html)
+
+- [需求提交:我们深知一个优秀的项目需要海纳百川,点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
+
+- [开源不易,求鼓励,点个star吧](https://github.com/click33/sa-token)
## ⭐ sa-token是什么?
-- **sa-token是一个JavaWeb轻量级权限认证框架,其API调用非常简单,有多简单呢?以登录验证为例,你只需要:**
+**sa-token是一个JavaWeb轻量级权限认证框架,其API调用非常简单,有多简单呢?以登录验证为例,你只需要:**
+
``` java
// 在登录时写入当前会话的账号id
-StpUtil.setLoginId(10001);
+StpUtil.setLoginId(10001);
+
+// 然后在任意需要校验登录处调用以下API --- 如果当前会话未登录,这句代码会抛出 `NotLoginException`异常
+StpUtil.checkLogin();
```
-- **然后在任意需要验证登录权限的地方:**
-``` java
-// 检测是否登录 --- 如果当前会话未登录,下面这句代码会抛出 `NotLoginException`异常
-StpUtil.checkLogin();
-```
-
-
-- **没有复杂的封装!不要任何的配置!先写入,后鉴权!只需这两行简单的调用,即可轻松完成系统登录鉴权!**
+**没有复杂的封装!不要任何的配置!只需这两行简单的调用,即可轻松完成系统登录鉴权!**
## 🔥 框架设计思想
@@ -47,20 +48,38 @@ StpUtil.checkLogin();
- 功能强大:能涵盖的功能全部涵盖,不让你用个框架还要自己给框架打各种补丁
+**如果上面的示例能够证明`sa-token`的简单,那么以下API则可以证明`sa-token`的强大**
+``` java
+StpUtil.setLoginId(10001); // 标记当前会话登录的账号id
+StpUtil.getLoginId(); // 获取当前会话登录的账号id
+StpUtil.isLogin(); // 获取当前会话是否已经登录, 返回true或false
+StpUtil.logout(); // 当前会话注销登录
+StpUtil.logoutByLoginId(10001); // 让账号为10001的会话注销登录(踢人下线)
+StpUtil.hasRole("super-admin"); // 查询当前账号是否含有指定角色标识, 返回true或false
+StpUtil.hasPermission("user:add"); // 查询当前账号是否含有指定权限, 返回true或false
+StpUtil.getSession(); // 获取当前账号id的Session
+StpUtil.getSessionByLoginId(10001); // 获取账号id为10001的Session
+StpUtil.getTokenValueByLoginId(10001); // 获取账号id为10001的token令牌值
+```
+**sa-token的API众多,请恕此处无法为您逐一展示,更多示例请戳官方在线文档**
+
+
+
+
## 💦️️ 涵盖功能
-- ⚡ **登录验证** —— 轻松登录鉴权,并提供五种细分场景值
-- ⚡ **权限验证** —— 拦截违规调用,不同角色不同授权
-- ⚡ **自定义session会话** —— 专业的数据缓存中心
-- ⚡ **踢人下线** —— 将违规用户立刻清退下线
-- ⚡ **模拟他人账号** —— 实时操作任意用户状态数据
-- ⚡ **持久层扩展** —— 可集成redis、MongoDB等专业缓存中间件
-- ⚡ **多账号认证体系** —— 比如一个商城项目的user表和admin表分开鉴权
-- ⚡ **无cookie模式** —— APP、小程序等前后台分离场景
-- ⚡ **注解式鉴权** —— 优雅的将鉴权与业务代码分离
-- ⚡ **花式token生成** —— 内置六种token风格,还可自定义token生成策略
-- ⚡ **自动续签** —— 提供两种token过期策略,灵活搭配使用,还可自动续签
-- ⚡ **组件自动注入** —— 零配置与Spring等框架集成
-- ⚡ **更多功能正在集成中...** —— 如有您有好想法或者建议,欢迎加群交流
+- **登录验证** —— 轻松登录鉴权,并提供五种细分场景值
+- **权限验证** —— 拦截违规调用,不同角色不同授权
+- **Session会话** —— 专业的数据缓存中心
+- **踢人下线** —— 将违规用户立刻清退下线
+- **模拟他人账号** —— 实时操作任意用户状态数据
+- **持久层扩展** —— 可集成redis、MongoDB等专业缓存中间件
+- **多账号认证体系** —— 比如一个商城项目的user表和admin表分开鉴权
+- **无Cookie模式** —— APP、小程序等前后台分离场景
+- **注解式鉴权** —— 优雅的将鉴权与业务代码分离
+- **花式token生成** —— 内置六种token风格,还可自定义token生成策略
+- **自动续签** —— 提供两种token过期策略,灵活搭配使用,还可自动续签
+- **组件自动注入** —— 零配置与Spring等框架集成
+- **更多功能正在集成中...** —— 如有您有好想法或者建议,欢迎加群交流
## 🔨 贡献代码
diff --git a/sa-token-doc/doc/_sidebar.md b/sa-token-doc/doc/_sidebar.md
index 3819b545..f0db84c1 100644
--- a/sa-token-doc/doc/_sidebar.md
+++ b/sa-token-doc/doc/_sidebar.md
@@ -8,10 +8,10 @@
- **使用**
- [登录验证](/use/login-auth)
- [权限验证](/use/jur-auth)
- - [session会话](/use/session)
+ - [Session会话](/use/session)
- [踢人下线](/use/kick)
- - [持久层扩展(集成redis)](/use/dao-extend)
- - [无cookie模式(前后台分离)](/use/not-cookie)
+ - [持久层扩展(集成Redis)](/use/dao-extend)
+ - [无Cookie模式(前后台分离)](/use/not-cookie)
- [模拟他人](/use/mock-person)
- [多账号验证](/use/many-account)
- [注解式鉴权](/use/at-check)
diff --git a/sa-token-doc/doc/index.html b/sa-token-doc/doc/index.html
index d181edd8..511f2746 100644
--- a/sa-token-doc/doc/index.html
+++ b/sa-token-doc/doc/index.html
@@ -7,7 +7,7 @@
-
+
@@ -22,6 +22,7 @@