v1.0.3版本更新

This commit is contained in:
2020-05-02 15:19:55 +08:00
parent 23d0e7106c
commit 16b20f38cd
26 changed files with 219 additions and 83 deletions

View File

@ -29,7 +29,7 @@
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</dependency>
<!-- SpringBoot整合redis -->

View File

@ -18,7 +18,7 @@ public class MySaTokenConfig extends WebMvcConfigurationSupport {
// public SaTokenConfig getSaTokenConfig() {
// SaTokenConfig config = new SaTokenConfig();
// config.setTokenName("satoken"); // token名称同时也是cookie名称
// config.setTimeout(30 * 24 * 60 * 60); // token有效期单位s 默认30天-1为永不过期
// 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里继续尝试读取
@ -29,7 +29,8 @@ public class MySaTokenConfig extends WebMvcConfigurationSupport {
// 注册sa-token的拦截器打开注解式鉴权功能
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaCheckInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new SaCheckInterceptor()).addPathPatterns("/**"); // 全局拦截器
}
}

View File

@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
// import org.springframework.stereotype.Component;
@ -29,10 +28,8 @@ public class SaTokenDaoRedis implements SaTokenDao {
@Autowired
@SuppressWarnings({ "rawtypes", "unchecked" })
public void setRedisTemplate(RedisTemplate redisTemplate) {
RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
JdkSerializationRedisSerializer jrSerializer = new JdkSerializationRedisSerializer();
redisTemplate.setValueSerializer(jrSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
this.redisTemplate = redisTemplate;
}

View File

@ -6,7 +6,6 @@ import java.util.List;
/**
* ajax返回Json的封装
* 此类封装了Meta和Body的功能写法不同但是返回数据格式相同
*/
public class AjaxJson implements Serializable{

View File

@ -31,6 +31,7 @@ public class TestController {
// System.out.println("当前是否登录:" + StpUtil.isLogin());
// System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull());
// 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());

View File

@ -17,7 +17,7 @@ import cn.dev33.satoken.exception.NotPermissionException;
/**
* 加强版控制器
*/
@ControllerAdvice // 可指定包前缀比如(basePackages = "com.zyd.blog.controller.admin")
@ControllerAdvice // 可指定包前缀比如(basePackages = "com.pj.admin")
public class TopController {
// 在每个控制器之前触发的操作
@ -31,27 +31,23 @@ public class TopController {
public void handlerException(Exception e, HttpServletRequest request, HttpServletResponse response)
throws Exception {
e.printStackTrace(); // 打印堆栈以供调试
// 打印堆栈以供调试
e.printStackTrace();
response.setContentType("application/json; charset=utf-8"); // http说明我要返回JSON对象
// 如果是未登录异常
if (e instanceof NotLoginException) {
String jsonStr = new ObjectMapper().writeValueAsString(AjaxJson.getNotLogin());
response.getWriter().print(jsonStr);
return;
}
// 如果是权限异常
if (e instanceof NotPermissionException) {
// 不同异常返回不同状态码
AjaxJson aj = null;
if (e instanceof NotLoginException) { // 如果是未登录异常
aj = AjaxJson.getNotLogin();
} else if(e instanceof NotPermissionException) { // 如果是权限异常
NotPermissionException ee = (NotPermissionException) e;
String jsonStr = new ObjectMapper().writeValueAsString(AjaxJson.getNotJur("无此权限:" + ee.getCode()));
response.getWriter().print(jsonStr);
return;
aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
} else { // 普通异常, 输出500 + 异常信息
aj = AjaxJson.getError(e.getMessage());
}
// 普通异常输出500 + 异常信息
response.getWriter().print(new ObjectMapper().writeValueAsString(AjaxJson.getError(e.getMessage())));
// 输出到客户端
response.setContentType("application/json; charset=utf-8"); // http说明我要返回JSON对象
response.getWriter().print(new ObjectMapper().writeValueAsString(aj));
}
}

View File

@ -7,7 +7,7 @@
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dev</artifactId>
<packaging>jar</packaging>
<version>1.0.2</version>
<version>1.0.3</version>
<!-- SpringBoot -->
<parent>

View File

@ -7,7 +7,7 @@ public class SaTokenUtil {
// sa-token 版本号
public static final String version = "v1.0.0";
public static final String version = "v1.0.3";
// sa-token 开源地址
public static final String github_url = "https://github.com/click33/sa-token";
@ -23,8 +23,8 @@ public class SaTokenUtil {
System.out.println(str);
}
// 如果token为本次请求新创建的则以此字符串为key存储在当前request中
public static final String just_created_save_key= "just_created_save_key_";
// 如果token为本次请求新创建的则以此字符串为key存储在当前request中 JUST_CREATED_SAVE_KEY
public static final String JUST_CREATED_SAVE_KEY= "JUST_CREATED_SAVE_KEY_";
}

View File

@ -6,6 +6,7 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
/**
@ -13,6 +14,28 @@ import cn.dev33.satoken.stp.StpUtil;
*/
public class SaCheckInterceptor implements HandlerInterceptor {
// 底层的 StpLogic 对象
public StpLogic stpLogic = null;
/**
* 创建并指定一个默认的 StpLogic
*/
public SaCheckInterceptor() {
this(StpUtil.stpLogic);
}
/**
* 创建并指定一个的 StpLogic
* @param stpLogic 指定的StpLogic
*/
public SaCheckInterceptor(StpLogic stpLogic) {
this.stpLogic = stpLogic;
}
// 每次请求之前触发
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
@ -26,7 +49,7 @@ public class SaCheckInterceptor implements HandlerInterceptor {
// 验证登录
if(method.hasMethodAnnotation(SaCheckLogin.class) || method.getBeanType().isAnnotationPresent(SaCheckLogin.class)) {
StpUtil.getLoginId();
stpLogic.checkLogin();
}
// 获取权限注解
@ -41,14 +64,17 @@ public class SaCheckInterceptor implements HandlerInterceptor {
// 开始验证权限
Object[] codeArray = concatABC(scp.value(), scp.valueInt(), scp.valueLong());
if(scp.isAnd()) {
StpUtil.checkPermissionAnd(codeArray); // 必须全部都有
stpLogic.checkPermissionAnd(codeArray); // 必须全部都有
} else {
StpUtil.checkPermissionOr(codeArray); // 有一个就行了
stpLogic.checkPermissionOr(codeArray); // 有一个就行了
}
return true;
}
// 合并三个数组
private Object[] concatABC(String[] a, int[] b, long[] c) {

View File

@ -6,7 +6,7 @@ package cn.dev33.satoken.config;
public class SaTokenConfig {
private String tokenName = "satoken"; // token名称同时也是cookie名称
private long timeout = 30 * 24 * 60 * 60; // token有效期单位s 默认30天-1为永不过期
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时继续从请求题参数里继续尝试读取

View File

@ -1,5 +1,7 @@
package cn.dev33.satoken.exception;
import cn.dev33.satoken.stp.StpUtil;
/**
* 没有登陆抛出的异常
*/
@ -9,13 +11,35 @@ public class NotLoginException extends RuntimeException {
*
*/
private static final long serialVersionUID = 6806129545290130142L;
/**
* login_key
*/
private String login_key;
/**
* 获得login_key
* @return login_key
*/
public String getLoginKey() {
return login_key;
}
/**
* 创建一个
*/
public NotLoginException() {
super("当前账号未登录");
this(StpUtil.stpLogic.login_key);
}
/**
* 创建一个
* @param login_key login_key
*/
public NotLoginException(String login_key) {
super("当前会话未登录"); // 这里到底要不要拼接上login_key呢纠结
this.login_key = login_key;
}
}

View File

@ -1,5 +1,7 @@
package cn.dev33.satoken.exception;
import cn.dev33.satoken.stp.StpUtil;
/**
* 没有指定权限码抛出的异常
*/
@ -10,24 +12,38 @@ public class NotPermissionException extends RuntimeException {
*/
private static final long serialVersionUID = 6806129545290130142L;
/**
* 权限码
*/
private Object code;
/**
* @return 获得权限码
*/
public Object getCode() {
return code;
}
/**
* login_key
*/
private String login_key;
/**
* 获得login_key
* @return login_key
*/
public String getLoginKey() {
return login_key;
}
public NotPermissionException(Object code) {
super("无此权限:" + code);
this(code, StpUtil.stpLogic.login_key);
}
public NotPermissionException(Object code, String login_key) {
super("无此权限:" + code); // 这里到底要不要拼接上login_key呢纠结
this.code = code;
this.login_key = login_key;
}
// public NotPermissionException(Object code, String s) {
// super(s);
// this.code = code;
// }
}

View File

@ -27,7 +27,7 @@ import cn.dev33.satoken.util.SpringMVCUtil;
public class StpLogic {
private String login_key = ""; // 持久化的key前缀多账号体系时以此值区分比如loginuseradmin
public String login_key = ""; // 持久化的key前缀多账号体系时以此值区分比如loginuseradmin
public StpLogic(String login_key) {
this.login_key = login_key;
@ -55,8 +55,8 @@ public class StpLogic {
String key_tokenName = getKey_tokenName();
// 1尝试从request里读取
if(request.getAttribute(SaTokenUtil.just_created_save_key) != null) {
return String.valueOf(request.getAttribute(SaTokenUtil.just_created_save_key));
if(request.getAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY) != null) {
return String.valueOf(request.getAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY));
}
// 2尝试从cookie里读取
@ -137,7 +137,7 @@ public class StpLogic {
// 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里
request.setAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY, tokenValue); // 保存到本次request里
SaCookieUtil.addCookie(SpringMVCUtil.getResponse(), getKey_tokenName(), tokenValue, "/", (int)config.getTimeout()); // cookie注入
}
@ -180,7 +180,14 @@ public class StpLogic {
public boolean isLogin() {
return getLoginId_defaultNull() != null;
}
/**
* 检验当前会话是否已经登录如未登录则抛出异常
*/
public void checkLogin() {
getLoginId();
}
/**
* 获取当前会话登录id, 如果未登录则抛出异常
* @return
@ -188,7 +195,7 @@ public class StpLogic {
public Object getLoginId() {
Object login_id = getLoginId_defaultNull();
if(login_id == null) {
throw new NotLoginException();
throw new NotLoginException(this.login_key);
}
return login_id;
}
@ -263,6 +270,19 @@ public class StpLogic {
return Long.valueOf(String.valueOf(getLoginId()));
}
/**
* 获取指定token对应的登录id如果未登录则返回 null
* @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;
}
}
return null;
}
// =================== session相关 ===================
@ -329,7 +349,7 @@ public class StpLogic {
*/
public void checkPermission(Object pcode) {
if(hasPermission(pcode) == false) {
throw new NotPermissionException(pcode);
throw new NotPermissionException(pcode, this.login_key);
}
}
@ -342,7 +362,7 @@ public class StpLogic {
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
for (Object pcode : pcodeArray) {
if(pcodeList.contains(pcode) == false) {
throw new NotPermissionException(pcode); // 没有权限抛出异常
throw new NotPermissionException(pcode, this.login_key); // 没有权限抛出异常
}
}
}
@ -360,7 +380,7 @@ public class StpLogic {
}
}
if(pcodeArray.length > 0) {
throw new NotPermissionException(pcodeArray[0]); // 没有权限抛出异常
throw new NotPermissionException(pcodeArray[0], this.login_key); // 没有权限抛出异常
}
}

View File

@ -79,6 +79,13 @@ public class StpUtil {
return stpLogic.isLogin();
}
/**
* 检验当前会话是否已经登录如未登录则抛出异常
*/
public static void checkLogin() {
getLoginId();
}
/**
* 获取当前会话登录id, 如果未登录则抛出异常
* @return
@ -128,6 +135,14 @@ public class StpUtil {
return stpLogic.getLoginId_asLong();
}
/**
* 获取指定token对应的登录id如果未登录则返回 null
* @return
*/
public static Object getLoginIdByToken(String tokenValue) {
return stpLogic.getLoginIdByToken(tokenValue);
}
// =================== session相关 ===================
/**

View File

@ -7,7 +7,7 @@ spring:
sa-token:
# token名称同时也是cookie名称
token-name: satoken
# token有效期单位s 默认30天-1为永不过期
# token有效期单位s 默认30天
timeout: 2592000
# 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录
is-share: true

View File

@ -2,7 +2,7 @@
- **开始**
- [介绍](/README)
- [下载](/start/download)
- [集成](/start/download)
- [示例](/start/example)
- **使用**

View File

@ -66,13 +66,13 @@
<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.2</sub>'
name += '<b style="font-size: 24px; vertical-align: middle;">sa-token</b> <sub>v1.0.3</sub>'
window.$docsify = {
name: name, // 名字
repo: 'https://github.com/click33/sa-token', // github地址
// themeColor: '#06A3D7', // 主题颜色
basePath: location.pathname.substr(0, location.pathname.lastIndexOf('/') + 1), // 自动计算项目名字
// basePath: '/sa-token-doc/', // 设置文件加载的父路径, 这在一些带项目名部署的文件中非常有效
// basePath: '/sa-token-doc/index.html',
auto2top: true, // 是否在切换页面后回到顶部
// coverpage: true, // 开启封面
subMaxLevel: 3, // 标题解析层级, 写几就在目录树中解析到几级标题 ,一般写2吧也就

View File

@ -2,8 +2,10 @@
---
- **SqlFly**[一个好用的ORM框架](https://sqlfly.dev33.cn/)
- **sa-admin**[一个基于多窗口后台模板, 强大、易用](http://sa-admin.dev33.cn/)
- **颜值排行榜:**[一个以颜值为讨论主题的社区](http://web.yanzhi21.com/)
- **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-doc**[一个基于markdown的接口文档编写工具](http://sa-doc.dev33.cn/)
- **SqlFly**[一个java语言的ORM框架](https://sqlfly.dev33.cn/)
- 虚位以待

View File

@ -1,7 +1,16 @@
# 更新日志
### 2020-5-2 @v1.0.3
- 新增:新增 `StpUtil.checkLogin()` 方法,更符合语义化的鉴权方法
- 新增:注册拦截器时可设置 `StpLogic` ,方便不同模块不同鉴权方式
- 新增:抛出异常时增加 `login_key` 区分,方便多账号体系鉴权处理
- 修复修复启动时的版本字符画版本号打印不对的bug
- 修复:修复文档部分不正确之处
- 新增:新增文档的友情链接
### 2020-3-7 @v1.0.2
- 新增:新增注解式验证,可在路由方法中使用注解进行权限验证,[注解式验证]()
- 新增:新增注解式验证,可在路由方法中使用注解进行权限验证
- 参考:[注解式验证](use/at-check)
### 2020-2-12 @v1.0.1

View File

@ -1,9 +1,23 @@
# 下载
# 集成
------
## maven依赖
在项目中直接通过 `pom.xml` 导入 `sa-token` 的依赖即可
``` xml
<!-- sa-token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token</artifactId>
<version>1.0.3</version>
</dependency>
```
## 源码
你可以通过`github`或者`gitee`来获取源码
如果你想深入了解`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吧
@ -15,18 +29,7 @@
## jar包下载
[点击下载sa-token-1.0.2.jar](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/sa-token-1.0.2.jar)
## maven依赖
``` xml
<!-- sa-token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token</artifactId>
<version>1.0.2</version>
</dependency>
```
[点击下载sa-token-1.0.3.jar](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/sa-token-1.0.3.jar)

View File

@ -18,7 +18,7 @@
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</dependency>
```
@ -32,7 +32,7 @@ spring:
sa-token:
# token名称同时也是cookie名称
token-name: satoken
# token有效期单位s 默认30天-1为永不过期
# token有效期单位s 默认30天
timeout: 2592000
# 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录
is-share: true

View File

@ -17,7 +17,7 @@
// 注册sa-token的拦截器打开注解式鉴权功能
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaCheckInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new SaCheckInterceptor()).addPathPatterns("/**"); // 全局拦截器
}
}
```
@ -46,4 +46,24 @@
```
#### 注意事项
以上两个注解都可以加在类上,代表为这个类所有方法进行鉴权
以上两个注解都可以加在类上,代表为这个类所有方法进行鉴权
## 3、扩展
- 其实在注册拦截器时,我们也可以根据路由前缀设置不同 `StpLogic`, 从而达到不同模块不同鉴权方式的目的
- 以下为参考示例:
``` java
@Configuration
public class MySaTokenConfig extends WebMvcConfigurationSupport {
// 注册sa-token的拦截器打开注解式鉴权功能
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaCheckInterceptor(StpUtil.stpLogic)).addPathPatterns("/admin/**");
registry.addInterceptor(new SaCheckInterceptor(StpUserUtil.stpLogic)).addPathPatterns("/user/**");
}
}
```

View File

@ -7,7 +7,7 @@
| 参数名称 | 类型 | 默认值 | 说明 |
| :-------- | :-------- | :-------- | :-------- |
| tokenName | String | satoken | token名称同时也是cookie名称 |
| timeout | long | 2592000 | token有效期单位s 默认30天-1为永不过期 |
| timeout | long | 2592000 | token有效期单位s 默认30天 |
| isShare | Boolean | true | 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录 |
| isReadHead| Boolean | true | 是否在cookie读取不到token时继续从请求header里继续尝试读取 |
| isReadBody| Boolean | true | 是否在header读取不到token时继续从请求题参数里继续尝试读取 |
@ -31,7 +31,7 @@
public SaTokenConfig getSaTokenConfig() {
SaTokenConfig config = new SaTokenConfig();
config.setTokenName("satoken"); // token名称同时也是cookie名称
config.setTimeout(30 * 24 * 60 * 60); // token有效期单位s 默认30天-1为永不过期
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里继续尝试读取
@ -50,7 +50,7 @@ spring:
sa-token:
# token名称同时也是cookie名称
token-name: satoken
# token有效期单位s 默认30天-1为永不过期
# token有效期单位s 默认30天
timeout: 2592000
# 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录
is-share: true

View File

@ -59,6 +59,7 @@ public class StpInterfaceImpl implements StpInterface {
#### StpUtil.checkPermission(Object pcode)
- 检测当前账号是否含有指定权限,如果有则安全通过,如果没有则抛出异常:`NotPermissionException`
- 扩展:`NotPermissionException` 对象可通过 `getLoginKey()` 方法获取具体是哪个 `StpLogic` 抛出的异常
#### StpUtil.checkPermissionAnd(Object... pcode)
- 检测当前账号是否含有指定权限【指定多个,必须全都有,否则抛出异常】

View File

@ -22,6 +22,10 @@
#### StpUtil.isLogin()
- 获取当前会话是否已经登录返回true=已登录false=未登录
#### StpUtil.checkLogin()
- 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`
- 扩展:`NotLoginException` 对象可通过 `getLoginKey()` 方法获取具体是哪个 `StpLogic` 抛出的异常
#### StpUtil.getLoginId()
- 获取当前会话登录id, 如果未登录,则抛出异常:`NotLoginException`
- 类似API还有
@ -34,5 +38,7 @@
- 类似API还有
- `StpUtil.getLoginId_defaultNull()` 获取当前会话登录id, 如果未登录则返回null
#### getLoginIdByToken(String tokenValue)
- 获取指定token对应的登录id如果未登录则返回 null

View File

@ -41,7 +41,7 @@
<!-- 内容部分 -->
<div class="main-box">
<div class="content-box">
<h1>sa-token<small>v1.0.2</small></h1>
<h1>sa-token<small>v1.0.3</small></h1>
<div class="sub-title">一个的JavaWeb权限认证框架强大、简单、好用</div>
<!-- <p>0配置开箱即用低学习成本</p> -->
<p>登录验证、权限验证、自定义session会话、踢人下线、持久层扩展、无cookie模式、模拟他人账号、多账号体系、注解式鉴权、Spring集成...</p>