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> <dependency>
<groupId>cn.dev33</groupId> <groupId>cn.dev33</groupId>
<artifactId>sa-token</artifactId> <artifactId>sa-token</artifactId>
<version>1.0.2</version> <version>1.0.3</version>
</dependency> </dependency>
<!-- SpringBoot整合redis --> <!-- SpringBoot整合redis -->

View File

@ -18,7 +18,7 @@ public class MySaTokenConfig extends WebMvcConfigurationSupport {
// public SaTokenConfig getSaTokenConfig() { // public SaTokenConfig getSaTokenConfig() {
// SaTokenConfig config = new SaTokenConfig(); // SaTokenConfig config = new SaTokenConfig();
// config.setTokenName("satoken"); // token名称同时也是cookie名称 // 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.setIsShare(true); // 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录
// config.setIsReadHead(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取 // config.setIsReadHead(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取
// config.setIsReadBody(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取 // config.setIsReadBody(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取
@ -29,7 +29,8 @@ public class MySaTokenConfig extends WebMvcConfigurationSupport {
// 注册sa-token的拦截器打开注解式鉴权功能 // 注册sa-token的拦截器打开注解式鉴权功能
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { 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.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
// import org.springframework.stereotype.Component; // import org.springframework.stereotype.Component;
@ -29,10 +28,8 @@ public class SaTokenDaoRedis implements SaTokenDao {
@Autowired @Autowired
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
public void setRedisTemplate(RedisTemplate redisTemplate) { public void setRedisTemplate(RedisTemplate redisTemplate) {
RedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
JdkSerializationRedisSerializer jrSerializer = new JdkSerializationRedisSerializer();
redisTemplate.setValueSerializer(jrSerializer);
this.redisTemplate = redisTemplate; this.redisTemplate = redisTemplate;
} }

View File

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

View File

@ -31,6 +31,7 @@ public class TestController {
// System.out.println("当前是否登录:" + StpUtil.isLogin()); // System.out.println("当前是否登录:" + StpUtil.isLogin());
// System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull()); // System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull());
// StpUtil.setLoginId(id); // 在当前会话登录此账号 // StpUtil.setLoginId(id); // 在当前会话登录此账号
// System.out.println("根据token找登录id" + StpUtil.getLoginIdByToken(StpUtil.getTokenValue()));
System.out.println("当前token信息" + StpUtil.getTokenInfo()); // 获取登录id并转为int System.out.println("当前token信息" + StpUtil.getTokenInfo()); // 获取登录id并转为int
System.out.println("当前登录账号:" + StpUtil.getLoginId_defaultNull()); 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 { public class TopController {
// 在每个控制器之前触发的操作 // 在每个控制器之前触发的操作
@ -31,27 +31,23 @@ public class TopController {
public void handlerException(Exception e, HttpServletRequest request, HttpServletResponse response) public void handlerException(Exception e, HttpServletRequest request, HttpServletResponse response)
throws Exception { throws Exception {
e.printStackTrace(); // 打印堆栈以供调试 // 打印堆栈以供调试
e.printStackTrace();
response.setContentType("application/json; charset=utf-8"); // http说明我要返回JSON对象 // 不同异常返回不同状态码
AjaxJson aj = null;
// 如果是未登录异常 if (e instanceof NotLoginException) { // 如果是未登录异常
if (e instanceof NotLoginException) { aj = AjaxJson.getNotLogin();
String jsonStr = new ObjectMapper().writeValueAsString(AjaxJson.getNotLogin()); } else if(e instanceof NotPermissionException) { // 如果是权限异常
response.getWriter().print(jsonStr);
return;
}
// 如果是权限异常
if (e instanceof NotPermissionException) {
NotPermissionException ee = (NotPermissionException) e; NotPermissionException ee = (NotPermissionException) e;
String jsonStr = new ObjectMapper().writeValueAsString(AjaxJson.getNotJur("无此权限:" + ee.getCode())); aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
response.getWriter().print(jsonStr); } else { // 普通异常, 输出500 + 异常信息
return; 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> <groupId>cn.dev33</groupId>
<artifactId>sa-token-dev</artifactId> <artifactId>sa-token-dev</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.2</version> <version>1.0.3</version>
<!-- SpringBoot --> <!-- SpringBoot -->
<parent> <parent>

View File

@ -7,7 +7,7 @@ public class SaTokenUtil {
// sa-token 版本号 // sa-token 版本号
public static final String version = "v1.0.0"; public static final String version = "v1.0.3";
// sa-token 开源地址 // sa-token 开源地址
public static final String github_url = "https://github.com/click33/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); System.out.println(str);
} }
// 如果token为本次请求新创建的则以此字符串为key存储在当前request中 // 如果token为本次请求新创建的则以此字符串为key存储在当前request中 JUST_CREATED_SAVE_KEY
public static final String just_created_save_key= "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.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
/** /**
@ -13,6 +14,28 @@ import cn.dev33.satoken.stp.StpUtil;
*/ */
public class SaCheckInterceptor implements HandlerInterceptor { 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 @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 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)) { 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()); Object[] codeArray = concatABC(scp.value(), scp.valueInt(), scp.valueLong());
if(scp.isAnd()) { if(scp.isAnd()) {
StpUtil.checkPermissionAnd(codeArray); // 必须全部都有 stpLogic.checkPermissionAnd(codeArray); // 必须全部都有
} else { } else {
StpUtil.checkPermissionOr(codeArray); // 有一个就行了 stpLogic.checkPermissionOr(codeArray); // 有一个就行了
} }
return true; return true;
} }
// 合并三个数组 // 合并三个数组
private Object[] concatABC(String[] a, int[] b, long[] c) { private Object[] concatABC(String[] a, int[] b, long[] c) {

View File

@ -6,7 +6,7 @@ package cn.dev33.satoken.config;
public class SaTokenConfig { public class SaTokenConfig {
private String tokenName = "satoken"; // token名称同时也是cookie名称 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 isShare = true; // 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录
private Boolean isReadHead = true; // 是否在cookie读取不到token时继续从请求header里继续尝试读取 private Boolean isReadHead = true; // 是否在cookie读取不到token时继续从请求header里继续尝试读取
private Boolean isReadBody = true; // 是否在header读取不到token时继续从请求题参数里继续尝试读取 private Boolean isReadBody = true; // 是否在header读取不到token时继续从请求题参数里继续尝试读取

View File

@ -1,5 +1,7 @@
package cn.dev33.satoken.exception; 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; 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() { 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; 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 static final long serialVersionUID = 6806129545290130142L;
/**
* 权限码
*/
private Object code; private Object code;
/** /**
* @return 获得权限码 * @return 获得权限码
*/ */
public Object getCode() { public Object getCode() {
return code; return code;
} }
/**
* login_key
*/
private String login_key;
/**
* 获得login_key
* @return login_key
*/
public String getLoginKey() {
return login_key;
}
public NotPermissionException(Object code) { 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.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 { public class StpLogic {
private String login_key = ""; // 持久化的key前缀多账号体系时以此值区分比如loginuseradmin public String login_key = ""; // 持久化的key前缀多账号体系时以此值区分比如loginuseradmin
public StpLogic(String login_key) { public StpLogic(String login_key) {
this.login_key = login_key; this.login_key = login_key;
@ -55,8 +55,8 @@ public class StpLogic {
String key_tokenName = getKey_tokenName(); String key_tokenName = getKey_tokenName();
// 1尝试从request里读取 // 1尝试从request里读取
if(request.getAttribute(SaTokenUtil.just_created_save_key) != null) { if(request.getAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY) != null) {
return String.valueOf(request.getAttribute(SaTokenUtil.just_created_save_key)); return String.valueOf(request.getAttribute(SaTokenUtil.JUST_CREATED_SAVE_KEY));
} }
// 2尝试从cookie里读取 // 2尝试从cookie里读取
@ -137,7 +137,7 @@ public class StpLogic {
// 3持久化 // 3持久化
dao.setValue(getKey_TokenValue(tokenValue), String.valueOf(login_id), config.getTimeout()); // token -> uid dao.setValue(getKey_TokenValue(tokenValue), String.valueOf(login_id), config.getTimeout()); // token -> uid
dao.setValue(getKey_LoginId(login_id), tokenValue, config.getTimeout()); // uid -> token 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注入 SaCookieUtil.addCookie(SpringMVCUtil.getResponse(), getKey_tokenName(), tokenValue, "/", (int)config.getTimeout()); // cookie注入
} }
@ -180,7 +180,14 @@ public class StpLogic {
public boolean isLogin() { public boolean isLogin() {
return getLoginId_defaultNull() != null; return getLoginId_defaultNull() != null;
} }
/**
* 检验当前会话是否已经登录如未登录则抛出异常
*/
public void checkLogin() {
getLoginId();
}
/** /**
* 获取当前会话登录id, 如果未登录则抛出异常 * 获取当前会话登录id, 如果未登录则抛出异常
* @return * @return
@ -188,7 +195,7 @@ public class StpLogic {
public Object getLoginId() { public Object getLoginId() {
Object login_id = getLoginId_defaultNull(); Object login_id = getLoginId_defaultNull();
if(login_id == null) { if(login_id == null) {
throw new NotLoginException(); throw new NotLoginException(this.login_key);
} }
return login_id; return login_id;
} }
@ -263,6 +270,19 @@ public class StpLogic {
return Long.valueOf(String.valueOf(getLoginId())); 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相关 =================== // =================== session相关 ===================
@ -329,7 +349,7 @@ public class StpLogic {
*/ */
public void checkPermission(Object pcode) { public void checkPermission(Object pcode) {
if(hasPermission(pcode) == false) { 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); List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
for (Object pcode : pcodeArray) { for (Object pcode : pcodeArray) {
if(pcodeList.contains(pcode) == false) { 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) { 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(); return stpLogic.isLogin();
} }
/**
* 检验当前会话是否已经登录如未登录则抛出异常
*/
public static void checkLogin() {
getLoginId();
}
/** /**
* 获取当前会话登录id, 如果未登录则抛出异常 * 获取当前会话登录id, 如果未登录则抛出异常
* @return * @return
@ -128,6 +135,14 @@ public class StpUtil {
return stpLogic.getLoginId_asLong(); return stpLogic.getLoginId_asLong();
} }
/**
* 获取指定token对应的登录id如果未登录则返回 null
* @return
*/
public static Object getLoginIdByToken(String tokenValue) {
return stpLogic.getLoginIdByToken(tokenValue);
}
// =================== session相关 =================== // =================== session相关 ===================
/** /**

View File

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

View File

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

View File

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

View File

@ -2,8 +2,10 @@
--- ---
- **SqlFly**[一个好用的ORM框架](https://sqlfly.dev33.cn/) - **sa-admin**[一个多窗口后台模板,流畅、易上手、提高生产力](http://sa-admin.dev33.cn/)
- **sa-admin**[一个基于多窗口后台模板, 强大、易用](http://sa-admin.dev33.cn/) - **sa-vue-admin**[对sa-admin的vue单页版实现, 基于vue-cli、element-ui的单页后台模板](http://sa-vue-admin.dev33.cn/)
- **颜值排行榜:**[一个以颜值为讨论主题的社区](http://web.yanzhi21.com/) - **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 ### 2020-3-7 @v1.0.2
- 新增:新增注解式验证,可在路由方法中使用注解进行权限验证,[注解式验证]() - 新增:新增注解式验证,可在路由方法中使用注解进行权限验证
- 参考:[注解式验证](use/at-check) - 参考:[注解式验证](use/at-check)
### 2020-2-12 @v1.0.1 ### 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) - 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) - gitee地址[https://gitee.com/sz6/sa-token](https://gitee.com/sz6/sa-token)
- 开源不易求鼓励给个star吧 - 开源不易求鼓励给个star吧
@ -15,18 +29,7 @@
## jar包下载 ## jar包下载
[点击下载sa-token-1.0.2.jar](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/sa-token-1.0.2.jar) [点击下载sa-token-1.0.3.jar](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/sa-token-1.0.3.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>
```

View File

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

View File

@ -17,7 +17,7 @@
// 注册sa-token的拦截器打开注解式鉴权功能 // 注册sa-token的拦截器打开注解式鉴权功能
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { 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名称 | | tokenName | String | satoken | token名称同时也是cookie名称 |
| timeout | long | 2592000 | token有效期单位s 默认30天-1为永不过期 | | timeout | long | 2592000 | token有效期单位s 默认30天 |
| isShare | Boolean | true | 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录 | | isShare | Boolean | true | 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录 |
| isReadHead| Boolean | true | 是否在cookie读取不到token时继续从请求header里继续尝试读取 | | isReadHead| Boolean | true | 是否在cookie读取不到token时继续从请求header里继续尝试读取 |
| isReadBody| Boolean | true | 是否在header读取不到token时继续从请求题参数里继续尝试读取 | | isReadBody| Boolean | true | 是否在header读取不到token时继续从请求题参数里继续尝试读取 |
@ -31,7 +31,7 @@
public SaTokenConfig getSaTokenConfig() { public SaTokenConfig getSaTokenConfig() {
SaTokenConfig config = new SaTokenConfig(); SaTokenConfig config = new SaTokenConfig();
config.setTokenName("satoken"); // token名称同时也是cookie名称 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.setIsShare(true); // 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录
config.setIsReadHead(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取 config.setIsReadHead(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取
config.setIsReadBody(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取 config.setIsReadBody(true); // 是否在cookie读取不到token时继续从请求header里继续尝试读取
@ -50,7 +50,7 @@ spring:
sa-token: sa-token:
# token名称同时也是cookie名称 # token名称同时也是cookie名称
token-name: satoken token-name: satoken
# token有效期单位s 默认30天-1为永不过期 # token有效期单位s 默认30天
timeout: 2592000 timeout: 2592000
# 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录 # 在多人登录同一账号时是否共享会话为true时共用一个为false时新登录挤掉旧登录
is-share: true is-share: true

View File

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

View File

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

View File

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