From ed18af72b8596aeb7fa90523a3e8388181695ff2 Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Sat, 30 Apr 2022 01:20:49 +0800 Subject: [PATCH] =?UTF-8?q?SSO=20=E6=A8=A1=E5=BC=8F=E4=B8=89=E7=9A=84?= =?UTF-8?q?=E6=97=A0=20sdk=20=E5=AF=B9=E6=8E=A5demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/dev33/satoken/json/SaJsonTemplate.java | 8 +- .../json/SaJsonTemplateDefaultImpl.java | 2 + .../.gitignore | 12 + .../sa-token-demo-sso3-client-nosdk/pom.xml | 36 +++ .../java/com/pj/SaSsoClientApplication.java | 14 ++ .../java/com/pj/sso/SsoClientController.java | 177 ++++++++++++++ .../main/java/com/pj/sso/SsoRequestUtil.java | 156 ++++++++++++ .../main/java/com/pj/sso/util/AjaxJson.java | 231 ++++++++++++++++++ .../com/pj/sso/util/MyHttpSessionHolder.java | 34 +++ .../src/main/resources/application.yml | 32 +++ 10 files changed, 698 insertions(+), 4 deletions(-) create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/.gitignore create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/pom.xml create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/SaSsoClientApplication.java create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoClientController.java create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoRequestUtil.java create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/AjaxJson.java create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/MyHttpSessionHolder.java create mode 100644 sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/resources/application.yml diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplate.java b/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplate.java index df83d8f8..f7dbff27 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplate.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplate.java @@ -11,13 +11,13 @@ import java.util.Map; public interface SaJsonTemplate { /** - * 将任意对象转换为 json 字符串 - * - * @param obj 对象 + * 将任意对象转换为 json 字符串 + * + * @param obj 对象 * @return 转换后的 json 字符串 */ public String toJsonString(Object obj); - + /** * 将 json 字符串解析为 Map * diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplateDefaultImpl.java b/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplateDefaultImpl.java index 5f551611..4a92e9b2 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplateDefaultImpl.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/json/SaJsonTemplateDefaultImpl.java @@ -17,6 +17,7 @@ public class SaJsonTemplateDefaultImpl implements SaJsonTemplate { /** * 将任意对象转换为 json 字符串 */ + @Override public String toJsonString(Object obj) { throw new ApiDisabledException(ERROR_MESSAGE); } @@ -24,6 +25,7 @@ public class SaJsonTemplateDefaultImpl implements SaJsonTemplate { /** * 将 json 字符串解析为 Map */ + @Override public Map parseJsonToMap(String jsonStr) { throw new ApiDisabledException(ERROR_MESSAGE); }; diff --git a/sa-token-demo/sa-token-demo-sso3-client-nosdk/.gitignore b/sa-token-demo/sa-token-demo-sso3-client-nosdk/.gitignore new file mode 100644 index 00000000..99a6e767 --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/.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-sso3-client-nosdk/pom.xml b/sa-token-demo/sa-token-demo-sso3-client-nosdk/pom.xml new file mode 100644 index 00000000..1fbd8d5d --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + cn.dev33 + sa-token-demo-sso3-client-nosdk + 0.0.1-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + com.ejlchina + okhttps + 3.1.1 + + + + + + + \ No newline at end of file diff --git a/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/SaSsoClientApplication.java b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/SaSsoClientApplication.java new file mode 100644 index 00000000..5a6393e2 --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/SaSsoClientApplication.java @@ -0,0 +1,14 @@ +package com.pj; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SaSsoClientApplication { + + public static void main(String[] args) { + SpringApplication.run(SaSsoClientApplication.class, args); + System.out.println("\nSa-Token SSO模式三 Client端 (无SDK版本) 启动成功"); + } + +} \ No newline at end of file diff --git a/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoClientController.java b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoClientController.java new file mode 100644 index 00000000..051d92fa --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoClientController.java @@ -0,0 +1,177 @@ +package com.pj.sso; + +import java.io.IOException; +import java.util.Objects; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.pj.sso.util.AjaxJson; +import com.pj.sso.util.MyHttpSessionHolder; + +/** + * SSO Client端 Controller + * @author kong + */ +@RestController +public class SsoClientController { + + // SSO-Client端:首页 + @RequestMapping("/") + public String index(HttpSession session) { + String str = "

Sa-Token SSO-Client 应用端

" + + "

当前会话登录账号:" + session.getAttribute("userId") + "

" + + "

登录" + + " 注销" + + " 获取资料

"; + return str; + } + + // SSO-Client端:单点登录地址 + @RequestMapping("/sso/login") + public Object ssoLogin(String ticket, @RequestParam(defaultValue = "/") String back, + HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException { + + // 如果已经登录,则直接返回 + if(session.getAttribute("userId") != null) { + response.sendRedirect(back); + return null; + } + + /* + * 此时有两种情况: + * 情况1:ticket无值,说明此请求是Client端访问,需要重定向至SSO认证中心 + * 情况2:ticket有值,说明此请求从SSO认证中心重定向而来,需要根据ticket进行登录 + */ + if(ticket == null) { + String currUrl = request.getRequestURL().toString(); + String clientLoginUrl = currUrl + "?back=" + SsoRequestUtil.encodeUrl(back); + String serverAuthUrl = SsoRequestUtil.authUrl + "?redirect=" + clientLoginUrl; + response.sendRedirect(serverAuthUrl); + return null; + } else { + // 获取当前 client 端的单点注销回调地址 + String ssoLogoutCall = ""; + if(SsoRequestUtil.isSlo) { + ssoLogoutCall = request.getRequestURL().toString().replace("/sso/login", "/sso/logoutCall"); + } + + // 校验 ticket + String checkUrl = SsoRequestUtil.checkTicketUrl + "?ticket=" + ticket + "&ssoLogoutCall=" + ssoLogoutCall; + AjaxJson result = SsoRequestUtil.request(checkUrl); + + // 200 代表校验成功 + if(result.getCode() == 200 && SsoRequestUtil.isEmpty(result.getData()) == false) { + // 登录上 + Object loginId = result.getData(); + session.setAttribute("userId", loginId); + // 返回 back 地址 + response.sendRedirect(back); + return null; + + } else { + // 将 sso-server 回应的消息作为异常抛出 + throw new RuntimeException(result.getMsg()); + } + } + } + + // SSO-Client端:单点注销地址 + @RequestMapping("/sso/logout") + public Object ssoLogout(@RequestParam(defaultValue = "/") String back, + HttpServletResponse response, HttpSession session) throws IOException { + + // 如果未登录,则无需注销 + if(session.getAttribute("userId") == null) { + response.sendRedirect(back); + return null; + } + + // 调用 sso-server 认证中心单点注销API + Object loginId = session.getAttribute("userId"); // 账号id + String timestamp = String.valueOf(System.currentTimeMillis()); // 时间戳 + String nonce = SsoRequestUtil.getRandomString(20); // 随机字符串 + String sign = SsoRequestUtil.getSign(loginId, timestamp, nonce, SsoRequestUtil.secretkey); // 参数签名 + + String url = SsoRequestUtil.sloUrl + + "?loginId=" + loginId + + "×tamp=" + timestamp + + "&nonce=" + nonce + + "&sign=" + sign; + AjaxJson result = SsoRequestUtil.request(url); + + // 校验响应状态码,200 代表成功 + if(result.getCode() == 200) { + + // 极端场景下,sso-server 中心的单点注销可能并不会通知到此 client 端,所以这里需要再补一刀 + session.removeAttribute("userId"); + // 返回 back 地址 + response.sendRedirect(back); + return null; + + } else { + // 将 sso-server 回应的消息作为异常抛出 + throw new RuntimeException(result.getMsg()); + } + } + + // SSO-Client端:单点注销回调地址 + @RequestMapping("/sso/logoutCall") + public Object ssoLogoutCall(String loginId, String timestamp, String nonce, String sign) { + + // 校验签名 + String calcSign = SsoRequestUtil.getSign(loginId, timestamp, nonce, SsoRequestUtil.secretkey); + if(calcSign.equals(sign) == false) { + return AjaxJson.getError("无效签名,拒绝应答"); + } + + // 注销这个账号id + for (HttpSession session: MyHttpSessionHolder.sessionList) { + Object userId = session.getAttribute("userId"); + if(Objects.equals(String.valueOf(userId), loginId)) { + session.removeAttribute("userId"); + } + } + + return AjaxJson.getSuccess("账号id=" + loginId + " 注销成功"); + } + + // 查询我的账号信息 (调用此接口的前提是 sso-server 端开放了 /sso/userinfo 路由) + @RequestMapping("/sso/myinfo") + public Object myinfo(HttpSession session) { + // 如果尚未登录 + if(session.getAttribute("userId") == null) { + return "尚未登录,无法获取"; + } + + // 组织 url 参数 + Object loginId = session.getAttribute("userId"); // 账号id + String timestamp = String.valueOf(System.currentTimeMillis()); // 时间戳 + String nonce = SsoRequestUtil.getRandomString(20); // 随机字符串 + String sign = SsoRequestUtil.getSign(loginId, timestamp, nonce, SsoRequestUtil.secretkey); // 参数签名 + + String url = SsoRequestUtil.userinfoUrl + + "?loginId=" + loginId + + "×tamp=" + timestamp + + "&nonce=" + nonce + + "&sign=" + sign; + AjaxJson result = SsoRequestUtil.request(url); + + // 返回给前端 + return result; + } + + // 全局异常拦截 + @ExceptionHandler + public AjaxJson handlerException(Exception e) { + e.printStackTrace(); + return AjaxJson.getError(e.getMessage()); + } + +} diff --git a/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoRequestUtil.java b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoRequestUtil.java new file mode 100644 index 00000000..81e17dc7 --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/SsoRequestUtil.java @@ -0,0 +1,156 @@ +package com.pj.sso; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.util.Map; +import java.util.Random; + +import com.ejlchina.okhttps.OkHttps; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.pj.sso.util.AjaxJson; + +/** + * 封装一些 sso 共用方法 + * + * @author kong + * @date: 2022-4-30 + */ +public class SsoRequestUtil { + + /** + * SSO-Server端 统一认证地址 + */ + public static String authUrl = "http://sa-sso-server.com:9000/sso/auth"; + + /** + * 使用 Http 请求校验ticket + */ +// public static boolean isHttp = true; + + /** + * SSO-Server端 ticket校验地址 + */ + public static String checkTicketUrl = "http://sa-sso-server.com:9000/sso/checkTicket"; + + /** + * 打开单点注销功能 + */ + public static boolean isSlo = true; + + /** + * 单点注销地址 + */ + public static String sloUrl = "http://sa-sso-server.com:9000/sso/logout"; + + /** + * 接口调用秘钥 + */ + public static String secretkey = "kQwIOrYvnXmSDkwEiFngrKidMcdrgKor"; + + /** + * SSO-Server端 查询userinfo地址 + */ + public static String userinfoUrl = "http://sa-sso-server.com:9000/sso/userinfo"; + + + // -------------------------- 工具方法 + + /** + * 发出请求,并返回 SaResult 结果 + * @param url 请求地址 + * @return 返回的结果 + */ + @SuppressWarnings("unchecked") + public static AjaxJson request(String url) { + String body = OkHttps.sync(url) + .post() + .getBody() + .toString(); + try { + Map map = new ObjectMapper().readValue(body, Map.class); + return new AjaxJson(map); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 根据参数计算签名 + * @param loginId 账号id + * @param timestamp 当前时间戳,13位 + * @param nonce 随机字符串 + * @param secretkey 账号id + * @return 签名 + */ + public static String getSign(Object loginId, String timestamp, String nonce, String secretkey) { + return md5("loginId=" + loginId + "&nonce=" + nonce + "×tamp=" + timestamp + "&key=" + secretkey); + } + + /** + * 指定元素是否为null或者空字符串 + * @param str 指定元素 + * @return 是否为null或者空字符串 + */ + public static boolean isEmpty(Object str) { + return str == null || "".equals(str); + } + + /** + * md5加密 + * @param str 指定字符串 + * @return 加密后的字符串 + */ + public static String md5(String str) { + str = (str == null ? "" : str); + char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + try { + byte[] btInput = str.getBytes(); + MessageDigest mdInst = MessageDigest.getInstance("MD5"); + mdInst.update(btInput); + byte[] md = mdInst.digest(); + int j = md.length; + char[] strA = new char[j * 2]; + int k = 0; + for (byte byte0 : md) { + strA[k++] = hexDigits[byte0 >>> 4 & 0xf]; + strA[k++] = hexDigits[byte0 & 0xf]; + } + return new String(strA); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 生成指定长度的随机字符串 + * + * @param length 字符串的长度 + * @return 一个随机字符串 + */ + public static String getRandomString(int length) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(62); + sb.append(str.charAt(number)); + } + return sb.toString(); + } + + /** + * 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 RuntimeException(e); + } + } + +} diff --git a/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/AjaxJson.java b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/AjaxJson.java new file mode 100644 index 00000000..4773c827 --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/AjaxJson.java @@ -0,0 +1,231 @@ +package com.pj.sso.util; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + + +/** + * ajax请求返回Json格式数据的封装
+ * 所有预留字段:
+ * code=状态码
+ * msg=描述信息
+ * data=携带对象
+ * pageNo=当前页
+ * pageSize=页大小
+ * startIndex=起始索引
+ * dataCount=数据总数
+ * pageCount=分页总数
+ *

返回范例:

+ *
+	{
+		"code": 200,    // 成功时=200, 失败时=500  msg=失败原因
+		"msg": "ok",
+		"data": {}
+	} 
+	
+ */ +public class AjaxJson extends LinkedHashMap 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; // 无效请求状态码 + + + + // ============================ 写值取值 ================================== + + /** 给code赋值,连缀风格 */ + public AjaxJson setCode(int code) { + this.put("code", code); + return this; + } + /** 返回code */ + public Integer getCode() { + return (Integer)this.get("code"); + } + + /** 给msg赋值,连缀风格 */ + public AjaxJson setMsg(String msg) { + this.put("msg", msg); + return this; + } + /** 获取msg */ + public String getMsg() { + return (String)this.get("msg"); + } + + /** 给data赋值,连缀风格 */ + public AjaxJson setData(Object data) { + this.put("data", data); + return this; + } + /** 获取data */ + public Object getData() { + return this.get("data"); + } + /** 将data还原为指定类型并返回 */ + @SuppressWarnings("unchecked") + public T getData(Class cs) { + return (T) this.getData(); + } + + /** 给dataCount(数据总数)赋值,连缀风格 */ + public AjaxJson setDataCount(Long dataCount) { + this.put("dataCount", dataCount); + // 如果提供了数据总数,则尝试计算page信息 + if(dataCount != null && dataCount >= 0) { + // 如果:已有page信息 + if(get("pageNo") != null) { + this.initPageInfo(); + } +// // 或者:是JavaWeb环境 +// else if(SoMap.isJavaWeb()) { +// SoMap so = SoMap.getRequestSoMap(); +// this.setPageNoAndSize(so.getKeyPageNo(), so.getKeyPageSize()); +// this.initPageInfo(); +// } + } + return this; + } + /** 获取dataCount(数据总数) */ + public Long getDataCount() { + return (Long)this.get("dataCount"); + } + + /** 设置pageNo 和 pageSize,并计算出startIndex于pageCount */ + public AjaxJson setPageNoAndSize(long pageNo, long pageSize) { + this.put("pageNo", pageNo); + this.put("pageSize", pageSize); + return this; + } + + /** 根据 pageSize dataCount,计算startIndex 与 pageCount */ + public AjaxJson initPageInfo() { + long pageNo = (long)this.get("pageNo"); + long pageSize = (long)this.get("pageSize"); + long dataCount = (long)this.get("dataCount"); + this.set("startIndex", (pageNo - 1) * pageSize); + long pc = dataCount / pageSize; + this.set("pageCount", (dataCount % pageSize == 0 ? pc : pc + 1)); + return this; + } + + + /** 写入一个值 自定义key, 连缀风格 */ + public AjaxJson set(String key, Object data) { + this.put(key, data); + return this; + } + + /** 写入一个Map, 连缀风格 */ + public AjaxJson setMap(Map map) { + for (String key : map.keySet()) { + this.put(key, map.get(key)); + } + return this; + } + + + // ============================ 构建 ================================== + + public AjaxJson(int code, String msg, Object data, Long dataCount) { + this.setCode(code); + this.setMsg(msg); + this.setData(data); + if(dataCount != null) { + this.setDataCount(dataCount); + } + } + + public AjaxJson(Map map) { + for (String key: map.keySet()) { + this.set(key, map.get(key)); + } + } + + /** 返回成功 */ + 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 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"); + } + + + + + + + +// // 历史版本遗留代码 +// public int code; // 状态码 +// public String msg; // 描述信息 +// public Object data; // 携带对象 +// public Long dataCount; // 数据总数,用于分页 + + + + +} diff --git a/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/MyHttpSessionHolder.java b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/MyHttpSessionHolder.java new file mode 100644 index 00000000..117fd561 --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/java/com/pj/sso/util/MyHttpSessionHolder.java @@ -0,0 +1,34 @@ +package com.pj.sso.util; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.springframework.stereotype.Component; + +/** + * 记录所有已创建的 HttpSession 对象 + * + * 此种方式有性能问题,仅做demo示例,真实项目中请更换为其它方案记录用户会话数据 + * + * @author kong + * @date: 2022-4-30 + */ +@Component +public class MyHttpSessionHolder implements HttpSessionListener { + + public static List sessionList = new ArrayList<>(); + + public void sessionCreated(HttpSessionEvent httpSessionEvent) { + sessionList.add(httpSessionEvent.getSession()); + } + + public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { + HttpSession session = httpSessionEvent.getSession(); + sessionList.remove(session); + } + +} diff --git a/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/resources/application.yml new file mode 100644 index 00000000..10e7e4c1 --- /dev/null +++ b/sa-token-demo/sa-token-demo-sso3-client-nosdk/src/main/resources/application.yml @@ -0,0 +1,32 @@ +# 端口 +server: + port: 9001 + +spring: + # 配置Sa-Token单独使用的Redis连接 (此处与SSO-Server端连接不同的Redis) + redis: + # Redis数据库索引 + database: 2 + # Redis服务器地址 + host: 127.0.0.1 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池最大连接数 + max-active: 200 + # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + # 连接池中的最大空闲连接 + max-idle: 10 + # 连接池中的最小空闲连接 + min-idle: 0 + + + + + \ No newline at end of file