From 857e260a0a253687120016256d5b4405cc114c37 Mon Sep 17 00:00:00 2001
From: shengzhang <2393584716@qq.com>
Date: Sun, 10 Jan 2021 18:36:35 +0800
Subject: [PATCH] =?UTF-8?q?jwt=E9=9B=86=E6=88=90=E7=A4=BA=E4=BE=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../satoken/exception/SaTokenException.java | 8 +
.../java/cn/dev33/satoken/stp/StpLogic.java | 26 +-
sa-token-demo-jwt/.gitignore | 12 +
sa-token-demo-jwt/pom.xml | 80 +++++++
.../com/pj/SaTokenJwtDemoApplication.java | 16 ++
.../com/pj/satoken/jwt/SaTokenJwtUtil.java | 225 ++++++++++++++++++
.../java/com/pj/test/GlobalException.java | 100 ++++++++
.../java/com/pj/test/TestJwtController.java | 60 +++++
.../src/main/java/com/pj/util/AjaxJson.java | 162 +++++++++++++
.../src/main/resources/application.yml | 45 ++++
sa-token-doc/doc/index.html | 2 +-
sa-token-doc/index.html | 2 +-
.../cn/dev33/satoken/aop/SaCheckAspect.java | 18 +-
13 files changed, 737 insertions(+), 19 deletions(-)
create mode 100644 sa-token-demo-jwt/.gitignore
create mode 100644 sa-token-demo-jwt/pom.xml
create mode 100644 sa-token-demo-jwt/src/main/java/com/pj/SaTokenJwtDemoApplication.java
create mode 100644 sa-token-demo-jwt/src/main/java/com/pj/satoken/jwt/SaTokenJwtUtil.java
create mode 100644 sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java
create mode 100644 sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java
create mode 100644 sa-token-demo-jwt/src/main/java/com/pj/util/AjaxJson.java
create mode 100644 sa-token-demo-jwt/src/main/resources/application.yml
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java b/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java
index a90a540b..00e77255 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java
@@ -21,5 +21,13 @@ public class SaTokenException extends RuntimeException {
super(message);
}
+ /**
+ * 构建一个异常
+ * @param cause 异常对象
+ */
+ public SaTokenException(Throwable cause) {
+ super(cause);
+ }
+
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
index ab2ea02d..80c69e6a 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
@@ -231,7 +231,7 @@ public class StpLogic {
clearLastActivity(tokenValue);
// 2. 尝试清除token-id键值对 (先从db中获取loginId值,如果根本查不到loginId,那么无需继续操作 )
- String loginId = SaTokenManager.getSaTokenDao().getValue(getKeyTokenValue(tokenValue));
+ String loginId = getLoginIdNotHandle(tokenValue);
if(loginId == null || NotLoginException.ABNORMAL_LIST.contains(loginId)) {
return;
}
@@ -317,7 +317,7 @@ public class StpLogic {
throw NotLoginException.newInstance(loginKey, NotLoginException.NOT_TOKEN);
}
// 查找此token对应loginId, 则抛出:无效token
- String loginId = SaTokenManager.getSaTokenDao().getValue(getKeyTokenValue(tokenValue));
+ String loginId = getLoginIdNotHandle(tokenValue);
if(loginId == null) {
throw NotLoginException.newInstance(loginKey, NotLoginException.INVALID_TOKEN);
}
@@ -377,7 +377,7 @@ public class StpLogic {
return null;
}
// loginId为null或者在异常项里面,均视为未登录
- Object loginId = SaTokenManager.getSaTokenDao().getValue(getKeyTokenValue(tokenValue));
+ Object loginId = getLoginIdNotHandle(tokenValue);
if(loginId == null || NotLoginException.ABNORMAL_LIST.contains(loginId)) {
return null;
}
@@ -427,16 +427,24 @@ public class StpLogic {
* @return 登录id
*/
public Object getLoginIdByToken(String tokenValue) {
- if(tokenValue != null) {
- Object loginId = SaTokenManager.getSaTokenDao().getValue(getKeyTokenValue(tokenValue));
- if(loginId != null) {
- return loginId;
- }
+ if(tokenValue == null) {
+ return null;
}
- return null;
+ return getLoginIdNotHandle(tokenValue);
}
+ /**
+ * 获取指定token对应的登录id (不做任何特殊处理)
+ * @param tokenValue token值
+ * @return loginId
+ */
+ public String getLoginIdNotHandle(String tokenValue) {
+ return SaTokenManager.getSaTokenDao().getValue(getKeyTokenValue(tokenValue));
+ }
+
+
+
// =================== session相关 ===================
/**
diff --git a/sa-token-demo-jwt/.gitignore b/sa-token-demo-jwt/.gitignore
new file mode 100644
index 00000000..99a6e767
--- /dev/null
+++ b/sa-token-demo-jwt/.gitignore
@@ -0,0 +1,12 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.idea/
+
+.factorypath
\ No newline at end of file
diff --git a/sa-token-demo-jwt/pom.xml b/sa-token-demo-jwt/pom.xml
new file mode 100644
index 00000000..38f28817
--- /dev/null
+++ b/sa-token-demo-jwt/pom.xml
@@ -0,0 +1,80 @@
+
+ 4.0.0
+ cn.dev33
+ sa-token-demo-jwt
+ 0.0.1-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot-starter
+ 1.11.0
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+
+
+
+
+
+ cn.dev33
+ sa-token-dao-redis-jackson
+ 1.11.0
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo-jwt/src/main/java/com/pj/SaTokenJwtDemoApplication.java b/sa-token-demo-jwt/src/main/java/com/pj/SaTokenJwtDemoApplication.java
new file mode 100644
index 00000000..10b42032
--- /dev/null
+++ b/sa-token-demo-jwt/src/main/java/com/pj/SaTokenJwtDemoApplication.java
@@ -0,0 +1,16 @@
+package com.pj;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import cn.dev33.satoken.SaTokenManager;
+
+@SpringBootApplication
+public class SaTokenJwtDemoApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SaTokenJwtDemoApplication.class, args);
+ System.out.println("\n启动成功:sa-token配置如下:" + SaTokenManager.getConfig());
+ }
+
+}
\ No newline at end of file
diff --git a/sa-token-demo-jwt/src/main/java/com/pj/satoken/jwt/SaTokenJwtUtil.java b/sa-token-demo-jwt/src/main/java/com/pj/satoken/jwt/SaTokenJwtUtil.java
new file mode 100644
index 00000000..7677824f
--- /dev/null
+++ b/sa-token-demo-jwt/src/main/java/com/pj/satoken/jwt/SaTokenJwtUtil.java
@@ -0,0 +1,225 @@
+package com.pj.satoken.jwt;
+
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.stereotype.Component;
+
+import cn.dev33.satoken.SaTokenManager;
+import cn.dev33.satoken.config.SaTokenConfig;
+import cn.dev33.satoken.dao.SaTokenDao;
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.exception.SaTokenException;
+import cn.dev33.satoken.session.SaSession;
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpLogic;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaTokenConsts;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.MalformedJwtException;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+@Component
+public class SaTokenJwtUtil {
+
+ /**
+ * 秘钥
+ */
+ public static final String BASE64_SECURITY = "79e7c69681b8270162386e6daa53d1dd";
+
+ /**
+ * token有效期 (单位: 秒)
+ */
+ public static final long TIMEOUT = 60 * 60 * 2;
+
+
+ public static final String LOGIN_ID_KEY = "loginId";
+
+
+ /**
+ * 根据userId生成token
+ * @param loginId 账号id
+ * @param base64Security 秘钥
+ * @return jwt-token
+ */
+ public static String createToken(Object loginId) {
+ // 判断,不可使用默认秘钥
+ if(BASE64_SECURITY.equals("79e7c69681b8270162386e6daa53d1d3")) {
+ throw new SaTokenException("请更换秘钥");
+ }
+ // 在这里你可以使用官方提供的claim方法构建载荷,也可以使用setPayload自定义载荷,但是两者不可一起使用
+ JwtBuilder builder = Jwts.builder()
+ .setHeaderParam("type", "JWT")
+ .claim(LOGIN_ID_KEY, loginId)
+ .setIssuedAt(new Date()) // 签发日期
+ .setExpiration(new Date(System.currentTimeMillis() + 1000 * TIMEOUT)) // 有效截止日期
+ .signWith(SignatureAlgorithm.HS256, BASE64_SECURITY.getBytes()); // 加密算法
+ //生成JWT
+ return builder.compact();
+ }
+
+ /**
+ * 从一个jwt里面解析出Claims
+ * @param tokenValue token值
+ * @param base64Security 秘钥
+ * @return Claims对象
+ */
+ public static Claims getClaims(String tokenValue) {
+// System.out.println(tokenValue);
+ Claims claims = Jwts.parser()
+ .setSigningKey(BASE64_SECURITY.getBytes())
+ .parseClaimsJws(tokenValue).getBody();
+ return claims;
+ }
+
+ /**
+ * 从一个jwt里面解析loginId
+ * @param tokenValue token值
+ * @param base64Security 秘钥
+ * @return loginId
+ */
+ public static String getLoginId(String tokenValue) {
+ try {
+ Object loginId = getClaims(tokenValue).get(LOGIN_ID_KEY);
+ if(loginId == null) {
+ return null;
+ }
+ return String.valueOf(loginId);
+ } catch (ExpiredJwtException e) {
+// throw NotLoginException.newInstance(StpUtil.stpLogic.loginKey, NotLoginException.TOKEN_TIMEOUT);
+ return NotLoginException.TOKEN_TIMEOUT;
+ } catch (MalformedJwtException e) {
+ throw NotLoginException.newInstance(StpUtil.stpLogic.loginKey, NotLoginException.INVALID_TOKEN);
+ } catch (Exception e) {
+ throw new SaTokenException(e);
+ }
+ }
+
+
+
+ static {
+
+ // 修改默认实现
+ StpUtil.stpLogic = new StpLogic("login") {
+
+ // 重写 (随机生成一个tokenValue)
+ @Override
+ public String createTokenValue(Object loginId) {
+ return SaTokenJwtUtil.createToken(loginId);
+ }
+
+ // 重写 (在当前会话上登录id )
+ @Override
+ public void setLoginId(Object loginId, String device) {
+ // ------ 1、获取相应对象
+ HttpServletRequest request = SaTokenManager.getSaTokenServlet().getRequest();
+ SaTokenConfig config = getConfig();
+ // ------ 2、生成一个token
+ String tokenValue = createTokenValue(loginId);
+ request.setAttribute(SaTokenConsts.JUST_CREATED_SAVE_KEY, tokenValue); // 将token保存到本次request里
+ if(config.getIsReadCookie() == true){ // cookie注入
+ SaTokenManager.getSaTokenCookie().addCookie(SaTokenManager.getSaTokenServlet().getResponse(), getTokenName(), tokenValue, "/", (int)config.getTimeout());
+ }
+ }
+
+ // 重写 (获取指定token对应的登录id)
+ @Override
+ public String getLoginIdNotHandle(String tokenValue) {
+ try {
+ return SaTokenJwtUtil.getLoginId(tokenValue);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ // 重写 (当前会话注销登录)
+ @Override
+ public void logout() {
+ // 如果连token都没有,那么无需执行任何操作
+ String tokenValue = getTokenValue();
+ if(tokenValue == null) {
+ return;
+ }
+ // 如果打开了cookie模式,把cookie清除掉
+ if(getConfig().getIsReadCookie() == true){
+ SaTokenManager.getSaTokenCookie().delCookie(SaTokenManager.getSaTokenServlet().getRequest(), SaTokenManager.getSaTokenServlet().getResponse(), getTokenName());
+ }
+ }
+
+ // 重写 (获取指定key的session)
+ @Override
+ public SaSession getSessionBySessionId(String sessionId, boolean isCreate) {
+ throw new SaTokenException("jwt has not session");
+ }
+
+ // 重写 (获取当前登录者的token剩余有效时间 (单位: 秒))
+ @Override
+ public long getTokenTimeout() {
+ // 如果没有token
+ String tokenValue = getTokenValue();
+ if(tokenValue == null) {
+ return SaTokenDao.NOT_VALUE_EXPIRE;
+ }
+ // 开始取值
+ Claims claims = null;
+ try {
+ claims = SaTokenJwtUtil.getClaims(tokenValue);
+ } catch (Exception e) {
+ return SaTokenDao.NOT_VALUE_EXPIRE;
+ }
+ if(claims == null) {
+ return SaTokenDao.NOT_VALUE_EXPIRE;
+ }
+ Date expiration = claims.getExpiration();
+ if(expiration == null) {
+ return SaTokenDao.NOT_VALUE_EXPIRE;
+ }
+ return (expiration.getTime() - System.currentTimeMillis()) / 1000;
+ }
+
+ // 重写 (返回当前token的登录设备)
+ @Override
+ public String getLoginDevice() {
+ return SaTokenConsts.DEFAULT_LOGIN_DEVICE;
+ }
+
+ // 重写 (获取当前会话的token信息)
+ @Override
+ public SaTokenInfo getTokenInfo() {
+ SaTokenInfo info = new SaTokenInfo();
+ info.tokenName = getTokenName();
+ info.tokenValue = getTokenValue();
+ info.isLogin = isLogin();
+ info.loginId = getLoginIdDefaultNull();
+ info.loginKey = getLoginKey();
+ info.tokenTimeout = getTokenTimeout();
+// info.sessionTimeout = getSessionTimeout();
+// info.tokenSessionTimeout = getTokenSessionTimeout();
+// info.tokenActivityTimeout = getTokenActivityTimeout();
+ info.loginDevice = getLoginDevice();
+ return info;
+ }
+
+
+ };
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java b/sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java
new file mode 100644
index 00000000..f128bcac
--- /dev/null
+++ b/sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java
@@ -0,0 +1,100 @@
+package com.pj.test;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import com.pj.util.AjaxJson;
+
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.exception.NotPermissionException;
+import cn.dev33.satoken.exception.NotRoleException;
+
+/**
+ * 全局异常处理
+ */
+@RestControllerAdvice // 可指定包前缀,比如:(basePackages = "com.pj.admin")
+public class GlobalException {
+
+ // 在每个控制器之前触发的操作
+ @ModelAttribute
+ public void get(HttpServletRequest request) throws IOException {
+
+ }
+
+
+
+
+ // 全局异常拦截(拦截项目中的所有异常)
+ @ExceptionHandler
+ public AjaxJson handlerException(Exception e, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ // 打印堆栈,以供调试
+ e.printStackTrace();
+
+ // 不同异常返回不同状态码
+ AjaxJson aj = null;
+ if (e instanceof NotLoginException) { // 如果是未登录异常
+ NotLoginException ee = (NotLoginException) e;
+ aj = AjaxJson.getNotLogin().setMsg(ee.getMessage());
+ } else if(e instanceof NotRoleException) { // 如果是角色异常
+ NotRoleException ee = (NotRoleException) e;
+ aj = AjaxJson.getNotJur("无此角色:" + ee.getRole());
+ } else if(e instanceof NotPermissionException) { // 如果是权限异常
+ NotPermissionException ee = (NotPermissionException) e;
+ aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
+ } else { // 普通异常, 输出:500 + 异常信息
+ aj = AjaxJson.getError(e.getMessage());
+ }
+
+ // 返回给前端
+ return aj;
+
+ // 输出到客户端
+// response.setContentType("application/json; charset=utf-8"); // http说明,我要返回JSON对象
+// response.getWriter().print(new ObjectMapper().writeValueAsString(aj));
+ }
+
+
+
+ // 全局异常拦截(拦截项目中的NotLoginException异常)
+// @ExceptionHandler(NotLoginException.class)
+// public AjaxJson handlerNotLoginException(NotLoginException nle, HttpServletRequest request, HttpServletResponse response)
+// throws Exception {
+//
+// // 打印堆栈,以供调试
+// nle.printStackTrace();
+//
+// // 判断场景值,定制化异常信息
+// String message = "";
+// if(nle.getType().equals(NotLoginException.NOT_TOKEN)) {
+// message = "未提供token";
+// }
+// else if(nle.getType().equals(NotLoginException.INVALID_TOKEN)) {
+// message = "token无效";
+// }
+// else if(nle.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
+// message = "token已过期";
+// }
+// else if(nle.getType().equals(NotLoginException.BE_REPLACED)) {
+// message = "token已被顶下线";
+// }
+// else if(nle.getType().equals(NotLoginException.KICK_OUT)) {
+// message = "token已被踢下线";
+// }
+// else {
+// message = "当前会话未登录";
+// }
+//
+// // 返回给前端
+// return AjaxJson.getError(message);
+// }
+
+
+}
diff --git a/sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java b/sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java
new file mode 100644
index 00000000..dc60ba28
--- /dev/null
+++ b/sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java
@@ -0,0 +1,60 @@
+package com.pj.test;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.util.AjaxJson;
+
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * 测试专用Controller
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/test/")
+public class TestJwtController {
+
+
+
+ // 测试登录接口, 浏览器访问: http://localhost:8081/test/login
+ @RequestMapping("login")
+ public AjaxJson login(@RequestParam(defaultValue="10001") String id) {
+ System.out.println("======================= 进入方法,测试登录接口 ========================= ");
+ 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("当前登录账号并转为int:" + StpUtil.getLoginIdAsInt());
+ System.out.println("当前登录设备:" + StpUtil.getLoginDevice());
+// System.out.println("当前token信息:" + StpUtil.getTokenInfo());
+
+ return AjaxJson.getSuccess();
+ }
+
+ // 打印当前token信息, 浏览器访问: http://localhost:8081/test/tokenInfo
+ @RequestMapping("tokenInfo")
+ public AjaxJson tokenInfo() {
+ System.out.println("======================= 进入方法,打印当前token信息 ========================= ");
+ SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
+ System.out.println(tokenInfo);
+ return AjaxJson.getSuccessData(tokenInfo);
+ }
+
+ // 测试 浏览器访问: http://localhost:8081/test/test
+ @RequestMapping("test")
+ public AjaxJson test() {
+ StpUtil.getTokenSession().logout();
+ StpUtil.logoutByLoginId(10001);
+ return AjaxJson.getSuccess();
+ }
+
+
+}
diff --git a/sa-token-demo-jwt/src/main/java/com/pj/util/AjaxJson.java b/sa-token-demo-jwt/src/main/java/com/pj/util/AjaxJson.java
new file mode 100644
index 00000000..768d0578
--- /dev/null
+++ b/sa-token-demo-jwt/src/main/java/com/pj/util/AjaxJson.java
@@ -0,0 +1,162 @@
+package com.pj.util;
+
+import java.io.Serializable;
+import java.util.List;
+
+
+/**
+ * ajax请求返回Json格式数据的封装
+ */
+public class AjaxJson implements Serializable{
+
+ private static final long serialVersionUID = 1L; // 序列化版本号
+
+ public static final int CODE_SUCCESS = 200; // 成功状态码
+ public static final int CODE_ERROR = 500; // 错误状态码
+ public static final int CODE_WARNING = 501; // 警告状态码
+ public static final int CODE_NOT_JUR = 403; // 无权限状态码
+ public static final int CODE_NOT_LOGIN = 401; // 未登录状态码
+ public static final int CODE_INVALID_REQUEST = 400; // 无效请求状态码
+
+ public int code; // 状态码
+ public String msg; // 描述信息
+ public Object data; // 携带对象
+ public Long dataCount; // 数据总数,用于分页
+
+ /**
+ * 返回code
+ * @return
+ */
+ public int getCode() {
+ return this.code;
+ }
+
+ /**
+ * 给msg赋值,连缀风格
+ */
+ public AjaxJson setMsg(String msg) {
+ this.msg = msg;
+ return this;
+ }
+ public String getMsg() {
+ return this.msg;
+ }
+
+ /**
+ * 给data赋值,连缀风格
+ */
+ public AjaxJson setData(Object data) {
+ this.data = data;
+ return this;
+ }
+
+ /**
+ * 将data还原为指定类型并返回
+ */
+ @SuppressWarnings("unchecked")
+ public T getData(Class cs) {
+ return (T) data;
+ }
+
+ // ============================ 构建 ==================================
+
+ public AjaxJson(int code, String msg, Object data, Long dataCount) {
+ this.code = code;
+ this.msg = msg;
+ this.data = data;
+ this.dataCount = dataCount;
+ }
+
+ // 返回成功
+ public static AjaxJson getSuccess() {
+ return new AjaxJson(CODE_SUCCESS, "ok", null, null);
+ }
+ public static AjaxJson getSuccess(String msg) {
+ return new AjaxJson(CODE_SUCCESS, msg, null, null);
+ }
+ public static AjaxJson getSuccess(String msg, Object data) {
+ return new AjaxJson(CODE_SUCCESS, msg, data, null);
+ }
+ public static AjaxJson getSuccessData(Object data) {
+ return new AjaxJson(CODE_SUCCESS, "ok", data, null);
+ }
+ public static AjaxJson getSuccessArray(Object... data) {
+ return new AjaxJson(CODE_SUCCESS, "ok", data, null);
+ }
+
+ // 返回失败
+ public static AjaxJson getError() {
+ return new AjaxJson(CODE_ERROR, "error", null, null);
+ }
+ public static AjaxJson getError(String msg) {
+ return new AjaxJson(CODE_ERROR, msg, null, null);
+ }
+
+ // 返回警告
+ public static AjaxJson getWarning() {
+ return new AjaxJson(CODE_ERROR, "warning", null, null);
+ }
+ public static AjaxJson getWarning(String msg) {
+ return new AjaxJson(CODE_WARNING, msg, null, null);
+ }
+
+ // 返回未登录
+ public static AjaxJson getNotLogin() {
+ return new AjaxJson(CODE_NOT_LOGIN, "未登录,请登录后再次访问", null, null);
+ }
+
+ // 返回没有权限的
+ public static AjaxJson getNotJur(String msg) {
+ return new AjaxJson(CODE_NOT_JUR, msg, null, null);
+ }
+
+ // 返回一个自定义状态码的
+ public static AjaxJson get(int code, String msg){
+ return new AjaxJson(code, msg, null, null);
+ }
+
+ // 返回分页和数据的
+ public static AjaxJson getPageData(Long dataCount, Object data){
+ return new AjaxJson(CODE_SUCCESS, "ok", data, dataCount);
+ }
+
+ // 返回,根据受影响行数的(大于0=ok,小于0=error)
+ public static AjaxJson getByLine(int line){
+ if(line > 0){
+ return getSuccess("ok", line);
+ }
+ return getError("error").setData(line);
+ }
+
+ // 返回,根据布尔值来确定最终结果的 (true=ok,false=error)
+ public static AjaxJson getByBoolean(boolean b){
+ return b ? getSuccess("ok") : getError("error");
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @SuppressWarnings("rawtypes")
+ @Override
+ public String toString() {
+ String data_string = null;
+ if(data == null){
+
+ } else if(data instanceof List){
+ data_string = "List(length=" + ((List)data).size() + ")";
+ } else {
+ data_string = data.toString();
+ }
+ return "{"
+ + "\"code\": " + this.getCode()
+ + ", \"msg\": \"" + this.getMsg() + "\""
+ + ", \"data\": " + data_string
+ + ", \"dataCount\": " + dataCount
+ + "}";
+ }
+
+
+
+
+
+}
diff --git a/sa-token-demo-jwt/src/main/resources/application.yml b/sa-token-demo-jwt/src/main/resources/application.yml
new file mode 100644
index 00000000..0ee1952f
--- /dev/null
+++ b/sa-token-demo-jwt/src/main/resources/application.yml
@@ -0,0 +1,45 @@
+# 端口
+server:
+ port: 8081
+
+spring:
+ # sa-token配置
+ sa-token:
+ # token名称 (同时也是cookie名称)
+ token-name: satoken
+ # token有效期,单位s 默认30天, -1代表永不过期
+ timeout: 2592000
+ # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
+ activity-timeout: -1
+ # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
+ allow-concurrent-login: true
+ # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
+ is-share: true
+ # token风格
+ token-style: uuid
+
+
+ # redis配置
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 0
+ # Redis服务器地址
+ host: 127.0.0.1
+ # Redis服务器连接端口
+ port: 6379
+ # Redis服务器连接密码(默认为空)
+ password:
+ # 连接超时时间(毫秒)
+ timeout: 10000ms
+ lettuce:
+ pool:
+ # 连接池最大连接数
+ max-active: 200
+ # 连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+ # 连接池中的最大空闲连接
+ max-idle: 10
+ # 连接池中的最小空闲连接
+ min-idle: 0
+
+
\ No newline at end of file
diff --git a/sa-token-doc/doc/index.html b/sa-token-doc/doc/index.html
index b6dfccfa..9aaf78d6 100644
--- a/sa-token-doc/doc/index.html
+++ b/sa-token-doc/doc/index.html
@@ -2,7 +2,7 @@
- sa-token
+ sa-token 官方文档
diff --git a/sa-token-doc/index.html b/sa-token-doc/index.html
index 5b441bdc..007a064a 100644
--- a/sa-token-doc/index.html
+++ b/sa-token-doc/index.html
@@ -2,7 +2,7 @@
- sa-token 官方文档
+ sa-token
diff --git a/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java b/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
index c68894e1..84a71c3d 100644
--- a/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
+++ b/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
@@ -19,16 +19,18 @@ import cn.dev33.satoken.stp.StpUtil;
public class SaCheckAspect {
/**
- * 底层的 StpLogic 对象
- */
- public StpLogic stpLogic = null;
-
- /**
- * 创建,并指定一个默认的 StpLogic
+ * 创建
*/
public SaCheckAspect() {
- this.stpLogic = StpUtil.stpLogic;
}
+
+ /**
+ * 获取本切面使用的StpLogic
+ */
+ public StpLogic getStpLogic() {
+ return StpUtil.stpLogic;
+ }
+
/**
* 定义AOP签名 (切入所有使用sa-token鉴权注解的方法)
@@ -54,7 +56,7 @@ public class SaCheckAspect {
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 注解鉴权
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- stpLogic.checkMethodAnnotation(signature.getMethod());
+ getStpLogic().checkMethodAnnotation(signature.getMethod());
try {
// 执行原有逻辑
Object obj = joinPoint.proceed();