From dd2665ceb10d79fad00450034544460bd9232c8c Mon Sep 17 00:00:00 2001
From: click33 <2393584716@qq.com>
Date: Thu, 24 Jun 2021 18:00:54 +0800
Subject: [PATCH] =?UTF-8?q?=E5=8D=95=E7=82=B9=E7=99=BB=E5=BD=95=EF=BC=9ACA?=
=?UTF-8?q?S=E6=A8=A1=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../cn/dev33/satoken/config/SaSsoConfig.java | 112 +++++++++++
.../dev33/satoken/config/SaTokenConfig.java | 26 ++-
.../satoken/context/model/SaRequest.java | 6 +
.../cn/dev33/satoken/sso/SaSsoConsts.java | 19 ++
.../cn/dev33/satoken/sso/SaSsoInterface.java | 180 ++++++++++++++++++
.../java/cn/dev33/satoken/sso/SaSsoUtil.java | 78 ++++++++
.../java/cn/dev33/satoken/util/SaFoxUtil.java | 105 +++++++++-
.../sa-token-demo-alone-redis/pom.xml | 2 +-
.../src/main/resources/application.yml | 22 +++
.../java/com/pj/SaTokenDemoApplication.java | 2 +-
.../src/main/resources/application.yml | 2 +-
.../sa-token-demo-sso-client/.gitignore | 12 ++
.../sa-token-demo-sso-client/pom.xml | 53 ++++++
.../java/com/pj/SaSsoClientApplication.java | 21 ++
.../java/com/pj/sso/SsoClientController.java | 49 +++++
.../src/main/java/com/pj/util/AjaxJson.java | 162 ++++++++++++++++
.../src/main/resources/application.yml | 45 +++++
.../sa-token-demo-sso-server/.gitignore | 12 ++
.../sa-token-demo-sso-server/pom.xml | 53 ++++++
.../java/com/pj/SaSsoServerApplication.java | 21 ++
.../main/java/com/pj/sso/GlobalException.java | 39 ++++
.../java/com/pj/sso/SsoServerController.java | 61 ++++++
.../src/main/java/com/pj/util/AjaxJson.java | 162 ++++++++++++++++
.../src/main/resources/application.yml | 46 +++++
.../com/pj/SaTokenWebfluxDemoApplication.java | 2 +-
.../src/main/resources/application.yml | 2 +-
sa-token-plugin/pom.xml | 3 +-
.../reactor/model/SaRequestForReactor.java | 8 +
.../servlet/model/SaRequestForServlet.java | 8 +
.../solon/model/SaRequestForSolon.java | 5 +
30 files changed, 1309 insertions(+), 9 deletions(-)
create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java
create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoInterface.java
create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java
create mode 100644 sa-token-demo/sa-token-demo-sso-client/.gitignore
create mode 100644 sa-token-demo/sa-token-demo-sso-client/pom.xml
create mode 100644 sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/SaSsoClientApplication.java
create mode 100644 sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/sso/SsoClientController.java
create mode 100644 sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/util/AjaxJson.java
create mode 100644 sa-token-demo/sa-token-demo-sso-client/src/main/resources/application.yml
create mode 100644 sa-token-demo/sa-token-demo-sso-server/.gitignore
create mode 100644 sa-token-demo/sa-token-demo-sso-server/pom.xml
create mode 100644 sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/SaSsoServerApplication.java
create mode 100644 sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/GlobalException.java
create mode 100644 sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java
create mode 100644 sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/util/AjaxJson.java
create mode 100644 sa-token-demo/sa-token-demo-sso-server/src/main/resources/application.yml
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
new file mode 100644
index 00000000..219d0c4d
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
@@ -0,0 +1,112 @@
+package cn.dev33.satoken.config;
+
+import cn.dev33.satoken.util.SaFoxUtil;
+
+/**
+ * Sa-Token-SSO 单点登录模块 配置Model
+ * @author kong
+ *
+ */
+public class SaSsoConfig {
+
+ /**
+ * Ticket有效期 (单位: 秒)
+ */
+ public long ticketTimeout = 60 * 5;
+
+ /**
+ * 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
+ */
+ public String allowUrl = "*";
+
+ /**
+ * 调用秘钥
+ */
+ public String secretkey;
+
+ /**
+ * SSO-Server端授权地址
+ */
+ public String serverUrl;
+
+ /**
+ * @return SSO-Server端授权地址
+ */
+ public String getServerUrl() {
+ return serverUrl;
+ }
+
+ /**
+ * @param serverUrl SSO-Server端授权地址
+ */
+ public void setServerUrl(String serverUrl) {
+ this.serverUrl = serverUrl;
+ }
+
+ /**
+ * @return Ticket有效期 (单位: 秒)
+ */
+ public long getTicketTimeout() {
+ return ticketTimeout;
+ }
+
+ /**
+ * @param ticketTimeout Ticket有效期 (单位: 秒)
+ * @return 对象自身
+ */
+ public SaSsoConfig setTicketTimeout(long ticketTimeout) {
+ this.ticketTimeout = ticketTimeout;
+ return this;
+ }
+
+ /**
+ * @return 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
+ */
+ public String getAllowUrl() {
+ return allowUrl;
+ }
+
+ /**
+ * @param allowUrl 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
+ * @return 对象自身
+ */
+ public SaSsoConfig setAllowUrl(String allowUrl) {
+ this.allowUrl = allowUrl;
+ return this;
+ }
+
+ /**
+ * @return 调用秘钥
+ */
+ public String getSecretkey() {
+ return secretkey;
+ }
+
+ /**
+ * @param secretkey 调用秘钥
+ * @return 对象自身
+ */
+ public SaSsoConfig setSecretkey(String secretkey) {
+ this.secretkey = secretkey;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "SaSsoConfig [ticketTimeout=" + ticketTimeout + ", allowUrl=" + allowUrl + ", secretkey=" + secretkey
+ + ", serverUrl=" + serverUrl + "]";
+ }
+
+
+
+ /**
+ * 以数组形式写入允许的授权回调地址
+ * @param url 所有集合
+ * @return 对象自身
+ */
+ public SaSsoConfig setAllow(String ...url) {
+ this.allowUrl = SaFoxUtil.arrayJoin(url);
+ return this;
+ }
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java
index 22a60311..2823d9c1 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java
@@ -66,6 +66,11 @@ public class SaTokenConfig {
*/
private String jwtSecretKey;
+ /**
+ * SSO单点登录配置对象
+ */
+ public SaSsoConfig sso = new SaSsoConfig();
+
/**
* @return token名称 (同时也是cookie名称)
@@ -343,6 +348,22 @@ public class SaTokenConfig {
return this;
}
+ /**
+ * @return SSO单点登录配置对象
+ */
+ public SaSsoConfig getSso() {
+ return sso;
+ }
+
+
+ /**
+ * @param sso SSO单点登录配置对象
+ */
+ public void setSso(SaSsoConfig sso) {
+ this.sso = sso;
+ }
+
+
/**
* toString()
*/
@@ -354,10 +375,12 @@ public class SaTokenConfig {
+ tokenStyle + ", dataRefreshPeriod=" + dataRefreshPeriod + ", tokenSessionCheckLogin="
+ tokenSessionCheckLogin + ", autoRenew=" + autoRenew + ", cookieDomain=" + cookieDomain
+ ", tokenPrefix=" + tokenPrefix + ", isPrint=" + isPrint + ", isLog=" + isLog + ", jwtSecretKey="
- + jwtSecretKey + "]";
+ + jwtSecretKey + ", sso=" + sso + "]";
}
+
+
/**
*
本函数设计已过时,未来版本可能移除此函数,请及时更换为 setIsConcurrent() ,使用方式保持不变
* @param allowConcurrentLogin see note
@@ -369,7 +392,6 @@ public class SaTokenConfig {
return this;
}
-
/**
* 本函数设计已过时,未来版本可能移除此函数,请及时更换为 setIsConcurrent() ,使用方式保持不变
* @param isV see note
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java b/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java
index d0d59cf0..c4584590 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java
@@ -40,6 +40,12 @@ public interface SaRequest {
*/
public String getRequestPath();
+ /**
+ * 返回当前请求的url,例:http://xxx.com/?id=127
+ * @return see note
+ */
+ public String getUrl();
+
/**
* 返回当前请求的类型
* @return see note
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java
new file mode 100644
index 00000000..aeac0479
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java
@@ -0,0 +1,19 @@
+package cn.dev33.satoken.sso;
+
+/**
+ * Sa-Token-SSO模块相关常量
+ * @author kong
+ *
+ */
+public class SaSsoConsts {
+
+ /** redirect参数名称 */
+ public static final String REDIRECT_NAME = "redirect";
+
+ /** ticket参数名称 */
+ public static final String TICKET_NAME = "ticket";
+
+ /** back参数名称 */
+ public static final String BACK_NAME = "back";
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoInterface.java b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoInterface.java
new file mode 100644
index 00000000..1cc124bc
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoInterface.java
@@ -0,0 +1,180 @@
+package cn.dev33.satoken.sso;
+
+import java.util.Arrays;
+import java.util.List;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.exception.SaTokenException;
+import cn.dev33.satoken.util.SaFoxUtil;
+
+/**
+ * Sa-Token-SSO 单点登录接口
+ * @author kong
+ *
+ */
+public interface SaSsoInterface {
+
+ /**
+ * 创建一个 Ticket码
+ * @param loginId 账号id
+ * @return 票据
+ */
+ public default String createTicket(Object loginId) {
+ // 随机一个ticket
+ String ticket = SaFoxUtil.getRandomString(64);
+
+ // 保存入库
+ long ticketTimeout = SaManager.getConfig().getSso().getTicketTimeout();
+ SaManager.getSaTokenDao().set(splicingKeyTicketToId(ticket), String.valueOf(loginId), ticketTimeout);
+ SaManager.getSaTokenDao().set(splicingKeyIdToTicket(loginId), String.valueOf(ticket), ticketTimeout);
+
+ // 返回
+ return ticket;
+ }
+
+ /**
+ * 删除一个 Ticket码
+ * @param ticket Ticket码
+ */
+ public default void deleteTicket(String ticket) {
+ SaManager.getSaTokenDao().delete(splicingKeyTicketToId(ticket));
+ }
+
+ /**
+ * 根据 账号id & 重定向地址,构建[SSO-Client端-重定向地址]
+ * @param loginId 账号id
+ * @param redirect 重定向地址
+ * @return [SSO-Client端-重定向地址]
+ */
+ public default String buildRedirectUrl(Object loginId, String redirect) {
+ // 校验授权地址
+ checkAuthUrl(redirect);
+
+ // 删掉旧ticket
+ String oldTicket = SaManager.getSaTokenDao().get(splicingKeyIdToTicket(loginId));
+ if(oldTicket != null) {
+ deleteTicket(oldTicket);
+ }
+
+ // 获取新ticket
+ String ticket = createTicket(loginId);
+
+ // 构建 授权重定向地址
+ redirect = encodeBackParam(redirect);
+ String redirectUrl = SaFoxUtil.joinParam(redirect, SaSsoConsts.TICKET_NAME + "=" + ticket);
+ return redirectUrl;
+ }
+
+ /**
+ * 根据 Ticket码 获取账号id,如果Ticket码无效则返回null
+ * @param ticket Ticket码
+ * @return 账号id
+ */
+ public default Object getLoginId(String ticket) {
+ if(SaFoxUtil.isEmpty(ticket)) {
+ return null;
+ }
+ return SaManager.getSaTokenDao().get(splicingKeyTicketToId(ticket));
+ }
+
+ /**
+ * 根据 Ticket码 获取账号id,并转换为指定类型
+ * @param ticket Ticket码
+ * @return 账号id
+ */
+ public default T getLoginId(String ticket, Class cs) {
+ return SaFoxUtil.getValueByType(getLoginId(ticket), cs);
+ }
+
+ /**
+ * 校验url合法性
+ * @param url 地址
+ */
+ public default void checkAuthUrl(String url) {
+
+ // 1、是否是一个有效的url
+ if(SaFoxUtil.isUrl(url) == false) {
+ throw new SaTokenException("无效回调地址:" + url);
+ }
+
+ // 2、是否在[允许地址列表]之中
+ String authUrl = SaManager.getConfig().getSso().getAllowUrl();
+ List authUrlList = Arrays.asList(authUrl.split(","));
+ if(SaManager.getSaTokenAction().hasElement(authUrlList, url) == false) {
+ throw new SaTokenException("非法回调地址:" + url);
+ }
+
+ // 验证通过
+ return;
+ }
+
+ /**
+ * 根据 Client端登录地址 & back地址 ,构建[SSO-Server端-认证地址]
+ * @param clientLoginUrl Client端登录地址
+ * @param back 回调路径
+ * @return [SSO-Server端-认证地址 ]
+ */
+ public default String buildServerAuthUrl(String clientLoginUrl, String back) {
+ // 服务端认证地址
+ String serverUrl = SaManager.getConfig().getSso().getServerUrl();
+
+ // 对back地址编码
+ back = (back == null ? "" : back);
+ back = SaFoxUtil.encodeUrl(back);
+
+ // 拼接最终地址,格式:serverAuthUrl = http://xxx.com?redirectUrl=xxx.com?back=xxx.com
+ clientLoginUrl = SaFoxUtil.joinParam(clientLoginUrl, SaSsoConsts.BACK_NAME + "=" + back);
+ String serverAuthUrl = SaFoxUtil.joinParam(serverUrl, SaSsoConsts.REDIRECT_NAME + "=" + clientLoginUrl);
+
+ // 返回
+ return serverAuthUrl;
+ }
+
+ /**
+ * 对url中的back参数进行URL编码, 解决超链接重定向后参数丢失的bug
+ * @param url url
+ * @return 编码过后的url
+ */
+ public default String encodeBackParam(String url) {
+
+ // 获取back参数所在位置
+ int index = url.indexOf("?" + SaSsoConsts.BACK_NAME + "=");
+ if(index == -1) {
+ index = url.indexOf("&" + SaSsoConsts.BACK_NAME + "=");
+ if(index == -1) {
+ return url;
+ }
+ }
+
+ // 开始编码
+ int length = SaSsoConsts.BACK_NAME.length() + 2;
+ String back = url.substring(index + length);
+ back = SaFoxUtil.encodeUrl(back);
+
+ // 放回url中
+ url = url.substring(0, index + length) + back;
+ return url;
+ }
+
+
+ // ------------------- 返回相应key -------------------
+
+ /**
+ * 拼接key:Ticket 查 账号Id
+ * @param ticket
+ * @return key
+ */
+ public default String splicingKeyTicketToId(String ticket) {
+ return SaManager.getConfig().getTokenName() + ":ticket:" + ticket;
+ }
+
+ /**
+ * 拼接key:账号Id 反查 Ticket
+ * @param id 账号id
+ * @return key
+ */
+ public default String splicingKeyIdToTicket(Object id) {
+ return SaManager.getConfig().getTokenName() + ":id-ticket:" + id;
+ }
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java
new file mode 100644
index 00000000..26172a9c
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java
@@ -0,0 +1,78 @@
+package cn.dev33.satoken.sso;
+
+/**
+ * Sa-Token-SSO 单点登录工具类
+ * @author kong
+ *
+ */
+public class SaSsoUtil {
+
+ /**
+ * 底层 SaSsoServerInterface 对象
+ */
+ public static SaSsoInterface saSsoInterface = new SaSsoInterface() {};
+
+ /**
+ * 创建一个 Ticket票据
+ * @param loginId 账号id
+ * @return 票据
+ */
+ public static String createTicket(Object loginId) {
+ return saSsoInterface.createTicket(loginId);
+ }
+
+ /**
+ * 删除一个 Ticket码
+ * @param ticket Ticket码
+ */
+ public static void deleteTicket(String ticket) {
+ saSsoInterface.deleteTicket(ticket);
+ }
+
+ /**
+ * 根据 账号id & 重定向地址,构建[SSO-Client端-重定向地址]
+ * @param loginId 账号id
+ * @param redirect 重定向地址
+ * @return [SSO-Client端-重定向地址]
+ */
+ public static String buildRedirectUrl(Object loginId, String redirect) {
+ return saSsoInterface.buildRedirectUrl(loginId, redirect);
+ }
+
+ /**
+ * 根据 Ticket码 获取账号id,如果Ticket码无效则返回null
+ * @param ticket Ticket码
+ * @return 账号id
+ */
+ public static Object getLoginId(String ticket) {
+ return saSsoInterface.getLoginId(ticket);
+ }
+
+ /**
+ * 根据 Ticket码 获取账号id,并转换为指定类型
+ * @param ticket Ticket码
+ * @return 账号id
+ */
+ public static T getLoginId(String ticket, Class cs) {
+ return saSsoInterface.getLoginId(ticket, cs);
+ }
+
+ /**
+ * 校验url合法性
+ * @param url 地址
+ */
+ public static void checkAuthUrl(String url) {
+ saSsoInterface.checkAuthUrl(url);
+ }
+
+ /**
+ * 根据 Client端登录地址 & back地址 ,构建[SSO-Server端-认证地址]
+ * @param clientLoginUrl Client端登录地址
+ * @param back 回调路径
+ * @return [SSO-Server端-认证地址 ]
+ */
+ public static String buildServerAuthUrl(String clientLoginUrl, String back) {
+ return saSsoInterface.buildServerAuthUrl(clientLoginUrl, back);
+ }
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java
index 42cee80e..ccd03e7d 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java
@@ -1,5 +1,8 @@
package cn.dev33.satoken.util;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -9,6 +12,8 @@ import java.util.List;
import java.util.Random;
import java.util.regex.Pattern;
+import cn.dev33.satoken.exception.SaTokenException;
+
/**
* Sa-Token 内部工具类
*
@@ -147,7 +152,6 @@ public class SaFoxUtil {
return Pattern.matches(patt.replaceAll("\\*", ".*"), str);
}
-
/**
* 将指定值转化为指定类型
* @param 泛型
@@ -186,5 +190,104 @@ public class SaFoxUtil {
return (T)obj3;
}
+ /**
+ * 在url上拼接上kv参数并返回
+ * @param url url
+ * @param parameStr 参数, 例如 id=1001
+ * @return 拼接后的url字符串
+ */
+ public static String joinParam(String url, String parameStr) {
+ // 如果参数为空, 直接返回
+ if(parameStr == null || parameStr.length() == 0) {
+ return url;
+ }
+ if(url == null) {
+ url = "";
+ }
+ int index = url.indexOf('?');
+ // ? 不存在
+ if(index == -1) {
+ return url + '?' + parameStr;
+ }
+ // ? 是最后一位
+ if(index == url.length() - 1) {
+ return url + parameStr;
+ }
+ // ? 是其中一位
+ if(index > -1 && index < url.length() - 1) {
+ String separatorChar = "&";
+ // 如果最后一位是 不是&, 且 parameStr 第一位不是 &, 就增送一个 &
+ if(url.lastIndexOf(separatorChar) != url.length() - 1 && parameStr.indexOf(separatorChar) != 0) {
+ return url + separatorChar + parameStr;
+ } else {
+ return url + parameStr;
+ }
+ }
+ // 正常情况下, 代码不可能执行到此
+ return url;
+ }
+
+ /**
+ * 将数组的所有元素使用逗号拼接在一起
+ * @param arr 数组
+ * @return 字符串,例: a,b,c
+ */
+ public static String arrayJoin(String[] arr) {
+ if(arr == null) {
+ return "";
+ }
+ String str = "";
+ for (int i = 0; i < arr.length; i++) {
+ str += arr[i];
+ if(i != arr.length - 1) {
+ str += ",";
+ }
+ }
+ return str;
+ }
+
+ /**
+ * 验证URL的正则表达式
+ */
+ public static final String URL_REGEX = "(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]";
+
+ /**
+ * 使用正则表达式判断一个字符串是否为URL
+ * @param str 字符串
+ * @return 拼接后的url字符串
+ */
+ public static boolean isUrl(String str) {
+ if(str == null) {
+ return false;
+ }
+ return str.toLowerCase().matches(URL_REGEX);
+ }
+
+ /**
+ * URL编码
+ * @param url see note
+ * @return see note
+ */
+ public static String encodeUrl(String url) {
+ try {
+ return URLEncoder.encode(url, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new SaTokenException(e);
+ }
+ }
+
+ /**
+ * URL解码
+ * @param url see note
+ * @return see note
+ */
+ public static String decoderUrl(String url) {
+ try {
+ return URLDecoder.decode(url, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new SaTokenException(e);
+ }
+ }
+
}
diff --git a/sa-token-demo/sa-token-demo-alone-redis/pom.xml b/sa-token-demo/sa-token-demo-alone-redis/pom.xml
index 53502013..9315a58b 100644
--- a/sa-token-demo/sa-token-demo-alone-redis/pom.xml
+++ b/sa-token-demo/sa-token-demo-alone-redis/pom.xml
@@ -41,7 +41,7 @@
cn.dev33
- sa-token-dao-redis
+ sa-token-dao-redis-jackson
${sa-token-version}
diff --git a/sa-token-demo/sa-token-demo-alone-redis/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-alone-redis/src/main/resources/application.yml
index 10b3b7cf..3976cdce 100644
--- a/sa-token-demo/sa-token-demo-alone-redis/src/main/resources/application.yml
+++ b/sa-token-demo/sa-token-demo-alone-redis/src/main/resources/application.yml
@@ -34,6 +34,28 @@ spring:
# 连接池中的最小空闲连接
min-idle: 0
+ # 配置业务使用的Redis连接
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 0
+ # Redis服务器地址
+ host: 127.0.0.1
+ # Redis服务器连接端口
+ port: 6379
+ # Redis服务器连接密码(默认为空)
+ password:
+ # 连接超时时间(毫秒)
+ timeout: 10ms
+ lettuce:
+ pool:
+ # 连接池最大连接数
+ max-active: 200
+ # 连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+ # 连接池中的最大空闲连接
+ max-idle: 10
+ # 连接池中的最小空闲连接
+ min-idle: 0
diff --git a/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java b/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java
index 03529d66..d024c158 100644
--- a/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java
+++ b/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/SaTokenDemoApplication.java
@@ -15,7 +15,7 @@ public class SaTokenDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SaTokenDemoApplication.class, args);
- System.out.println("\n启动成功:sa-token配置如下:" + SaManager.getConfig());
+ System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
}
}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-springboot/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-springboot/src/main/resources/application.yml
index b5024ee4..f0f2da76 100644
--- a/sa-token-demo/sa-token-demo-springboot/src/main/resources/application.yml
+++ b/sa-token-demo/sa-token-demo-springboot/src/main/resources/application.yml
@@ -31,7 +31,7 @@ spring:
# Redis服务器连接密码(默认为空)
password:
# 连接超时时间(毫秒)
- timeout: 10000ms
+ timeout: 10ms
lettuce:
pool:
# 连接池最大连接数
diff --git a/sa-token-demo/sa-token-demo-sso-client/.gitignore b/sa-token-demo/sa-token-demo-sso-client/.gitignore
new file mode 100644
index 00000000..99a6e767
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-client/.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/sa-token-demo-sso-client/pom.xml b/sa-token-demo/sa-token-demo-sso-client/pom.xml
new file mode 100644
index 00000000..66b1461f
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-client/pom.xml
@@ -0,0 +1,53 @@
+
+ 4.0.0
+ cn.dev33
+ sa-token-demo-sso-client
+ 0.0.1-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+
+ 1.20.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot-starter
+ ${sa-token-version}
+
+
+
+
+ cn.dev33
+ sa-token-dao-redis-jackson
+ ${sa-token-version}
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/SaSsoClientApplication.java b/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/SaSsoClientApplication.java
new file mode 100644
index 00000000..0248e60e
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/SaSsoClientApplication.java
@@ -0,0 +1,21 @@
+package com.pj;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import cn.dev33.satoken.SaManager;
+
+/**
+ * Sa-Token整合SpringBoot 示例
+ * @author kong
+ *
+ */
+@SpringBootApplication
+public class SaSsoClientApplication {
+
+ public static void main(String[] args) throws ClassNotFoundException {
+ SpringApplication.run(SaSsoClientApplication.class, args);
+ System.out.println("\nSa-Token-SSO客户端启动成功:Sa-Token配置如下:" + SaManager.getConfig());
+ }
+
+}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/sso/SsoClientController.java b/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/sso/SsoClientController.java
new file mode 100644
index 00000000..75269760
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/sso/SsoClientController.java
@@ -0,0 +1,49 @@
+package com.pj.sso;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.ModelAndView;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.sso.SaSsoUtil;
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * Sa-Token-SSO Client端 Controller
+ * @author kong
+ */
+@RestController
+public class SsoClientController {
+
+ // Client端登录地址
+ @RequestMapping("ssoLogin")
+ public Object login(String back, String ticket) {
+ // 如果当前已经登录,则无需访问SSO认证中心,可以直接返回
+ System.out.println("是否已登录:" + StpUtil.isLogin());
+ if(StpUtil.isLogin()) {
+ return new ModelAndView("redirect:" + back);
+ }
+ /*
+ * 接下来两种情况:
+ * ticket有值,说明此请求从SSO认证中心重定向而来,需要根据ticket进行登录
+ * ticket无值,说明此请求是Client端访问,需要重定向至SSO认证中心
+ */
+ if(ticket != null) {
+ Object loginId = SaSsoUtil.getLoginId(ticket);
+ if(loginId != null ) {
+ // 如果ticket是有效的 (可以获取到值),需要就此登录 且清除此ticket
+ StpUtil.login(loginId);
+ SaSsoUtil.deleteTicket(ticket);
+ // 最后重定向回back地址
+ return new ModelAndView("redirect:" + back);
+ }
+ // 此处向客户端提示ticket无效即可,不要重定向到SSO认证中心,否则容易引起无限重定向
+ return "ticket无效: " + ticket;
+ }
+
+ // 重定向至 SSO-Server端 认证地址
+ String serverAuthUrl = SaSsoUtil.buildServerAuthUrl(SaHolder.getRequest().getUrl(), back);
+ return new ModelAndView("redirect:" + serverAuthUrl);
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/util/AjaxJson.java b/sa-token-demo/sa-token-demo-sso-client/src/main/java/com/pj/util/AjaxJson.java
new file mode 100644
index 00000000..768d0578
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-client/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/sa-token-demo-sso-client/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-sso-client/src/main/resources/application.yml
new file mode 100644
index 00000000..77e9919e
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-client/src/main/resources/application.yml
@@ -0,0 +1,45 @@
+# 端口
+server:
+ port: 9001
+
+spring:
+ # sa-token配置
+ sa-token:
+ # Token名称
+ token-name: satoken
+ # Token有效期
+ timeout: 2592000
+ # Token风格
+ token-style: uuid
+ # SSO-相关配置
+ sso:
+ # SSO-Server端授权地址
+ server-url: http://sa-sso-server.com:9000/ssoAuth
+
+ # redis配置
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 0
+ # Redis服务器地址
+ host: 127.0.0.1
+ # Redis服务器连接端口
+ port: 6379
+ # Redis服务器连接密码(默认为空)
+ password:
+ # 连接超时时间(毫秒)
+ timeout: 10ms
+ 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-demo/sa-token-demo-sso-server/.gitignore b/sa-token-demo/sa-token-demo-sso-server/.gitignore
new file mode 100644
index 00000000..99a6e767
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-server/.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/sa-token-demo-sso-server/pom.xml b/sa-token-demo/sa-token-demo-sso-server/pom.xml
new file mode 100644
index 00000000..5d9d600a
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-server/pom.xml
@@ -0,0 +1,53 @@
+
+ 4.0.0
+ cn.dev33
+ sa-token-demo-sso-server
+ 0.0.1-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+
+ 1.20.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot-starter
+ ${sa-token-version}
+
+
+
+
+ cn.dev33
+ sa-token-dao-redis-jackson
+ ${sa-token-version}
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/SaSsoServerApplication.java b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/SaSsoServerApplication.java
new file mode 100644
index 00000000..f2ac5be3
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/SaSsoServerApplication.java
@@ -0,0 +1,21 @@
+package com.pj;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import cn.dev33.satoken.SaManager;
+
+/**
+ * Sa-Token整合SpringBoot 示例
+ * @author kong
+ *
+ */
+@SpringBootApplication
+public class SaSsoServerApplication {
+
+ public static void main(String[] args) throws ClassNotFoundException {
+ SpringApplication.run(SaSsoServerApplication.class, args);
+ System.out.println("\nSa-Token-SSO 服务端启动成功:Sa-Token配置如下:" + SaManager.getConfig());
+ }
+
+}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/GlobalException.java b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/GlobalException.java
new file mode 100644
index 00000000..52ab707a
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/GlobalException.java
@@ -0,0 +1,39 @@
+package com.pj.sso;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.pj.util.AjaxJson;
+
+/**
+ * 全局异常处理
+ */
+@ControllerAdvice // 可指定包前缀,比如:(basePackages = "com.pj.admin")
+public class GlobalException {
+
+ // 全局异常拦截(拦截项目中的所有异常)
+ @ResponseBody
+ @ExceptionHandler
+ public AjaxJson handlerException(Exception e, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ // 打印堆栈,以供调试
+ System.out.println("全局异常---------------");
+ e.printStackTrace();
+
+ // 不同异常返回不同状态码
+ AjaxJson aj = AjaxJson.getError(e.getMessage());
+
+ // 返回给前端
+ return aj;
+
+ // 输出到客户端
+// response.setContentType("application/json; charset=utf-8"); // http说明,我要返回JSON对象
+// response.getWriter().print(new ObjectMapper().writeValueAsString(aj));
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java
new file mode 100644
index 00000000..b772c485
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java
@@ -0,0 +1,61 @@
+package com.pj.sso;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.pj.util.AjaxJson;
+
+import cn.dev33.satoken.sso.SaSsoUtil;
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * Sa-Token-SSO Server端 Controller
+ * @author kong
+ *
+ */
+@RestController
+public class SsoServerController {
+
+ // SSO-Server端:授权地址,跳转到登录页面
+ @RequestMapping("ssoAuth")
+ public Object ssoAuth(String redirect) {
+ /*
+ * 两种情况分开处理:
+ * 1、如果在SSO认证中心尚未登录,则先去登登录
+ * 2、如果在SSO认证中心尚已登录,则开始对redirect地址下放ticket引导授权
+ */
+ // 情况1:尚未登录
+ if(StpUtil.isLogin() == false) {
+ String msg = "当前会话在SSO-Server端尚未登录,请先访问"
+ + " doLogin登录 "
+ + "进行登录之后,刷新页面开始授权";
+ return msg;
+ }
+ // 情况2:已经登录,开始构建授权重定向地址,下放ticket
+ String redirectUrl = SaSsoUtil.buildRedirectUrl(StpUtil.getLoginId(), redirect);
+ return new ModelAndView("redirect:" + redirectUrl);
+ }
+
+ // SSO-Server端:登录接口
+ @RequestMapping("doLogin")
+ public AjaxJson doLogin(String name, String pwd) {
+ if("sa".equals(name) && "123456".equals(pwd)) {
+ StpUtil.login(10001);
+ return AjaxJson.getSuccess("登录成功!");
+ }
+ return AjaxJson.getError("登录失败!");
+ }
+
+ // SSO-Server端:根据 Ticket 获取账号id
+ @RequestMapping("getLoginId")
+ public AjaxJson getLoginId(String ticket) {
+ Object loginId = SaSsoUtil.getLoginId(ticket);
+ if(loginId != null) {
+ SaSsoUtil.deleteTicket(ticket);
+ return AjaxJson.getSuccessData(loginId);
+ }
+ return AjaxJson.getError("无效ticket: " + ticket);
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/util/AjaxJson.java b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/util/AjaxJson.java
new file mode 100644
index 00000000..768d0578
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-server/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/sa-token-demo-sso-server/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-sso-server/src/main/resources/application.yml
new file mode 100644
index 00000000..6242e765
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso-server/src/main/resources/application.yml
@@ -0,0 +1,46 @@
+# 端口
+server:
+ port: 9000
+
+spring:
+ # Sa-Token配置
+ sa-token:
+ # Token名称
+ token-name: satoken
+ # Token有效期
+ timeout: 2592000
+ # Token风格
+ token-style: uuid
+ # SSO单点登录-相关配置
+# sso:
+# allow-url: http*
+
+
+ # redis配置
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 0
+ # Redis服务器地址
+ host: 127.0.0.1
+ # Redis服务器连接端口
+ port: 6379
+ # Redis服务器连接密码(默认为空)
+ password:
+ # 连接超时时间(毫秒)
+ timeout: 10ms
+ 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-demo/sa-token-demo-webflux/src/main/java/com/pj/SaTokenWebfluxDemoApplication.java b/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/SaTokenWebfluxDemoApplication.java
index 89081671..c3914628 100644
--- a/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/SaTokenWebfluxDemoApplication.java
+++ b/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/SaTokenWebfluxDemoApplication.java
@@ -26,7 +26,7 @@ public class SaTokenWebfluxDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SaTokenWebfluxDemoApplication.class, args);
- System.out.println("\n启动成功:sa-token配置如下:" + SaManager.getConfig());
+ System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
}
}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-webflux/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-webflux/src/main/resources/application.yml
index 0ee1952f..7ecd9cfa 100644
--- a/sa-token-demo/sa-token-demo-webflux/src/main/resources/application.yml
+++ b/sa-token-demo/sa-token-demo-webflux/src/main/resources/application.yml
@@ -12,7 +12,7 @@ spring:
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
- allow-concurrent-login: true
+ is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: true
# token风格
diff --git a/sa-token-plugin/pom.xml b/sa-token-plugin/pom.xml
index 3f0fd74c..1e93e670 100644
--- a/sa-token-plugin/pom.xml
+++ b/sa-token-plugin/pom.xml
@@ -17,11 +17,12 @@
+ sa-token-alone-redis
sa-token-dao-redis
sa-token-dao-redis-jackson
- sa-token-spring-aop
sa-token-quick-login
+ sa-token-spring-aop
sa-token-temp-jwt
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java
index e98ff31c..ae54e932 100644
--- a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java
@@ -70,6 +70,14 @@ public class SaRequestForReactor implements SaRequest {
return request.getURI().getPath();
}
+ /**
+ * 返回当前请求的url,例:http://xxx.com/?id=127
+ * @return see note
+ */
+ public String getUrl() {
+ return request.getURI().toString();
+ }
+
/**
* 返回当前请求的类型
*/
diff --git a/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java b/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java
index 1e1ae812..c0a28b9d 100644
--- a/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java
+++ b/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java
@@ -73,6 +73,14 @@ public class SaRequestForServlet implements SaRequest {
return request.getServletPath();
}
+ /**
+ * 返回当前请求的url,例:http://xxx.com/?id=127
+ * @return see note
+ */
+ public String getUrl() {
+ return request.getRequestURL().toString();
+ }
+
/**
* 返回当前请求的类型
*/
diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java
index c98e7a77..4a32c964 100644
--- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java
+++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java
@@ -40,6 +40,11 @@ public class SaRequestForSolon implements SaRequest {
return ctx.pathNew();
}
+ @Override
+ public String getUrl() {
+ return ctx.url();
+ }
+
@Override
public String getMethod() {
return ctx.method();