From 35cf52c684367acf7fddd4f74b96bfcae29ae999 Mon Sep 17 00:00:00 2001
From: click33 <2393584716@qq.com>
Date: Thu, 26 Aug 2021 23:17:39 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=8D=95=E7=82=B9=E7=99=BB?=
=?UTF-8?q?=E5=BD=95demo?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
mvn clean.bat | 8 +
.../sa-token-demo-sso1-client/.gitignore | 12 ++
.../sa-token-demo-sso1-client/pom.xml | 60 +++++++
.../java/com/pj/SaSsoClientApplication.java | 19 ++
.../java/com/pj/sso/SsoClientController.java | 39 +++++
.../src/main/resources/application.yml | 40 +++++
.../sa-token-demo-sso1-server/.gitignore | 12 ++
.../sa-token-demo-sso1-server/pom.xml | 57 ++++++
.../java/com/pj/SaSsoServerApplication.java | 19 ++
.../java/com/pj/sso/SsoServerController.java | 62 +++++++
.../src/main/resources/application.yml | 38 ++++
.../main/resources/static/sa-res/login.css | 59 +++++++
.../src/main/resources/static/sa-res/login.js | 65 +++++++
.../main/resources/templates/sa-login.html | 45 +++++
.../main/java/com/pj/SaSsoApplication.java | 22 ++-
.../main/java/com/pj/sso/SsoController.java | 13 +-
.../src/main/java/com/pj/util/AjaxJson.java | 162 ------------------
sa-token-doc/doc/sso/readme.md | 24 +--
sa-token-doc/doc/sso/sso-type1.md | 78 +++++++--
sa-token-doc/doc/sso/sso-type2.md | 7 +-
sa-token-doc/doc/start/download.md | 4 +-
21 files changed, 644 insertions(+), 201 deletions(-)
create mode 100644 sa-token-demo/sa-token-demo-sso1-client/.gitignore
create mode 100644 sa-token-demo/sa-token-demo-sso1-client/pom.xml
create mode 100644 sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/SaSsoClientApplication.java
create mode 100644 sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java
create mode 100644 sa-token-demo/sa-token-demo-sso1-client/src/main/resources/application.yml
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/.gitignore
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/pom.xml
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/SaSsoServerApplication.java
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/sso/SsoServerController.java
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/src/main/resources/application.yml
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.css
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.js
create mode 100644 sa-token-demo/sa-token-demo-sso1-server/src/main/resources/templates/sa-login.html
delete mode 100644 sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/util/AjaxJson.java
diff --git a/mvn clean.bat b/mvn clean.bat
index 6c5badfc..3714ac9b 100644
--- a/mvn clean.bat
+++ b/mvn clean.bat
@@ -41,6 +41,14 @@ cd sa-token-demo-sso1
call mvn clean
cd ..
+cd sa-token-demo-sso1-server
+call mvn clean
+cd ..
+
+cd sa-token-demo-sso1-client
+call mvn clean
+cd ..
+
cd sa-token-demo-sso2-server
call mvn clean
cd ..
diff --git a/sa-token-demo/sa-token-demo-sso1-client/.gitignore b/sa-token-demo/sa-token-demo-sso1-client/.gitignore
new file mode 100644
index 00000000..99a6e767
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-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-sso1-client/pom.xml b/sa-token-demo/sa-token-demo-sso1-client/pom.xml
new file mode 100644
index 00000000..63ab9b45
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-client/pom.xml
@@ -0,0 +1,60 @@
+
+ 4.0.0
+ cn.dev33
+ sa-token-demo-sso1-client
+ 0.0.1-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+
+ 1.25.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
+
+
+
+
+ cn.dev33
+ sa-token-alone-redis
+ ${sa-token-version}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/SaSsoClientApplication.java b/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/SaSsoClientApplication.java
new file mode 100644
index 00000000..48a0c842
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/SaSsoClientApplication.java
@@ -0,0 +1,19 @@
+package com.pj;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * SSO模式一,Client端 Demo
+ * @author kong
+ *
+ */
+@SpringBootApplication
+public class SaSsoClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SaSsoClientApplication.class, args);
+ System.out.println("\nSa-Token-SSO Client端启动成功");
+ }
+
+}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java b/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java
new file mode 100644
index 00000000..d4a87d3f
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java
@@ -0,0 +1,39 @@
+package com.pj.sso;
+
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * Sa-Token-SSO Client端 Controller
+ * @author kong
+ */
+@RestController
+public class SsoClientController {
+
+ /*
+ * SSO-Client端:首页
+ */
+ @RequestMapping("/")
+ public String index() {
+ String authUrl = SaManager.getConfig().getSso().getAuthUrl();
+ String solUrl = SaManager.getConfig().getSso().getSloUrl();
+ String str = "
Sa-Token SSO-Client 应用端
" +
+ "当前会话是否登录:" + StpUtil.isLogin() + "
" +
+ "登录 " +
+ "注销
";
+ return str;
+ }
+
+ // 全局异常拦截
+ @ExceptionHandler
+ public SaResult handlerException(Exception e) {
+ e.printStackTrace();
+ return SaResult.error(e.getMessage());
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-sso1-client/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-sso1-client/src/main/resources/application.yml
new file mode 100644
index 00000000..2ad21326
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-client/src/main/resources/application.yml
@@ -0,0 +1,40 @@
+# 端口
+server:
+ port: 9001
+
+# sa-token配置
+sa-token:
+ # SSO-相关配置
+ sso:
+ # SSO-Server端 单点登录地址
+ auth-url: http://sso.stp.com:9000/sso/auth
+ # SSO-Server端 单点注销地址
+ slo-url: http://sso.stp.com:9000/sso/logout
+
+ # 配置Sa-Token单独使用的Redis连接 (此处需要和SSO-Server端连接同一个Redis)
+ alone-redis:
+ # Redis数据库索引
+ database: 1
+ # 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
diff --git a/sa-token-demo/sa-token-demo-sso1-server/.gitignore b/sa-token-demo/sa-token-demo-sso1-server/.gitignore
new file mode 100644
index 00000000..99a6e767
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-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-sso1-server/pom.xml b/sa-token-demo/sa-token-demo-sso1-server/pom.xml
new file mode 100644
index 00000000..33ec3120
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-server/pom.xml
@@ -0,0 +1,57 @@
+
+ 4.0.0
+ cn.dev33
+ sa-token-demo-sso1-server
+ 0.0.1-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+
+ 1.25.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
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/SaSsoServerApplication.java b/sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/SaSsoServerApplication.java
new file mode 100644
index 00000000..90ab6e4f
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/SaSsoServerApplication.java
@@ -0,0 +1,19 @@
+package com.pj;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * SSO模式一,Server端 Demo
+ * @author kong
+ *
+ */
+@SpringBootApplication
+public class SaSsoServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SaSsoServerApplication.class, args);
+ System.out.println("\nSa-Token-SSO 认证中心启动成功");
+ }
+
+}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/sso/SsoServerController.java b/sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/sso/SsoServerController.java
new file mode 100644
index 00000000..df5a39c7
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-server/src/main/java/com/pj/sso/SsoServerController.java
@@ -0,0 +1,62 @@
+package com.pj.sso;
+
+import org.springframework.web.bind.annotation.ExceptionHandler;
+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.stp.StpUtil;
+import cn.dev33.satoken.util.SaFoxUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * Sa-Token-SSO Server端 Controller
+ * @author kong
+ *
+ */
+@RestController
+public class SsoServerController {
+
+ /*
+ * SSO-Server端:统一登录地址
+ */
+ @RequestMapping("/sso/auth")
+ public Object ssoAuth(String redirect) {
+ // 如果尚未登录,则返回登录视图进行登录
+ if(StpUtil.isLogin() == false) {
+ return new ModelAndView("sa-login.html");
+ }
+ // 如果已登录,则原路返回到 Client端
+ return SaHolder.getResponse().redirect(redirect);
+ }
+
+ // 处理登录请求
+ @RequestMapping("/sso/doLogin")
+ public SaResult ssoDoLogin(String name, String pwd) {
+ // 模拟登录
+ if("sa".equals(name) && "123456".equals(pwd)) {
+ StpUtil.login(10001);
+ return SaResult.ok("登录成功!");
+ }
+ return SaResult.error("登录失败!");
+ }
+
+ // 单点注销地址
+ @RequestMapping("/sso/logout")
+ public Object ssoLogout(String back) {
+ StpUtil.logout();
+ if(SaFoxUtil.isEmpty(back)) {
+ return SaResult.ok();
+ }
+ return SaHolder.getResponse().redirect(back);
+ }
+
+ // 全局异常拦截
+ @ExceptionHandler
+ public SaResult handlerException(Exception e) {
+ e.printStackTrace();
+ return SaResult.error(e.getMessage());
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/application.yml
new file mode 100644
index 00000000..9ed905fa
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/application.yml
@@ -0,0 +1,38 @@
+# 端口
+server:
+ port: 9000
+
+# Sa-Token配置
+sa-token:
+ # 写入Cookie时显式指定的作用域, 用于单点登录二级域名共享Cookie
+ cookie-domain: stp.com
+
+spring:
+ # Redis配置
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 1
+ # 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
diff --git a/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.css b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.css
new file mode 100644
index 00000000..f831a49f
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.css
@@ -0,0 +1,59 @@
+*{margin: 0; padding: 0;}
+body{font-family: Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif;}
+::-webkit-input-placeholder{color: #ccc;}
+
+/* 视图盒子 */
+.view-box{position: relative; width: 100vw; height: 100vh; overflow: hidden;}
+/* 背景 EAEFF3 */
+.bg-1{height: 50%; background: linear-gradient(to bottom right, #0466c5, #3496F5);}
+.bg-2{height: 50%; background-color: #EAEFF3;}
+
+/* 渐变背景 */
+/*.bg-1{
+ background-size: 500%;
+ background-image: linear-gradient(125deg,#0466c5,#3496F5,#0466c5,#3496F5,#0466c5,#2496F5);
+ animation: bganimation 30s infinite;
+}
+@keyframes bganimation{
+ 0%{background-position: 0% 50%;}
+ 50%{background-position: 100% 50%;}
+ 100%{background-position: 0% 50%;}
+} */
+/* 背景 */
+.bg-1{background: #101C34;}
+.bg-2{background: #101C34;}
+/* .bg-1{height: 100%; background-image: url(./login-bg.png); background-size: 100% 100%;} */
+
+
+/* 内容盒子 */
+.content-box{position: absolute; width: 100vw; height: 100vh; top: 0px;}
+
+/* 登录盒子 */
+/* .login-box{width: 400px; height: 400px; position: absolute; left: calc(50% - 200px); top: calc(50% - 200px); max-width: 90%; } */
+.login-box{width: 400px; margin: auto; max-width: 90%; height: 100%;}
+.login-box{display: flex; align-items: center; text-align: center;}
+
+/* 表单 */
+.from-box{flex: 1; padding: 20px 50px; background-color: #FFF;}
+.from-box{border-radius: 1px; box-shadow: 1px 1px 20px #666;}
+.from-title{margin-top: 20px; margin-bottom: 30px; text-align: center;}
+
+/* 输入框 */
+.from-item{border: 0px #000 solid; margin-bottom: 15px;}
+.s-input{width: 100%; line-height: 32px; height: 32px; text-indent: 1em; outline: 0; border: 1px #ccc solid; border-radius: 3px; transition: all 0.2s;}
+.s-input{font-size: 12px;}
+.s-input:focus{border-color: #409eff}
+
+/* 登录按钮 */
+.s-btn{ text-indent: 0; cursor: pointer; background-color: #409EFF; border-color: #409EFF; color: #FFF;}
+.s-btn:hover{background-color: #50aEFF;}
+
+/* 重置按钮 */
+.reset-box{text-align: left; font-size: 12px;}
+.reset-box a{text-decoration: none;}
+.reset-box a:hover{text-decoration: underline;}
+
+/* loading框样式 */
+.ajax-layer-load.layui-layer-dialog{min-width: 0px !important; background-color: rgba(0,0,0,0.85);}
+.ajax-layer-load.layui-layer-dialog .layui-layer-content{padding: 10px 20px 10px 40px; color: #FFF;}
+.ajax-layer-load.layui-layer-dialog .layui-layer-content .layui-layer-ico{width: 20px; height: 20px; background-size: 20px 20px; top: 12px; }
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.js b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.js
new file mode 100644
index 00000000..f581ee78
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/static/sa-res/login.js
@@ -0,0 +1,65 @@
+// sa
+var sa = {};
+
+// 打开loading
+sa.loading = function(msg) {
+ layer.closeAll(); // 开始前先把所有弹窗关了
+ return layer.msg(msg, {icon: 16, shade: 0.3, time: 1000 * 20, skin: 'ajax-layer-load' });
+};
+
+// 隐藏loading
+sa.hideLoading = function() {
+ layer.closeAll();
+};
+
+
+// ----------------------------------- 登录事件 -----------------------------------
+
+$('.login-btn').click(function(){
+ sa.loading("正在登录...");
+ // 开始登录
+ setTimeout(function() {
+ $.ajax({
+ url: "sso/doLogin",
+ type: "post",
+ data: {
+ name: $('[name=name]').val(),
+ pwd: $('[name=pwd]').val()
+ },
+ dataType: 'json',
+ success: function(res){
+ console.log('返回数据:', res);
+ sa.hideLoading();
+ if(res.code == 200) {
+ layer.msg('登录成功', {anim: 0, icon: 6 });
+ setTimeout(function() {
+ location.reload();
+ }, 800)
+ } else {
+ layer.msg(res.msg, {anim: 6, icon: 2 });
+ }
+ },
+ error: function(xhr, type, errorThrown){
+ sa.hideLoading();
+ if(xhr.status == 0){
+ return layer.alert('无法连接到服务器,请检查网络');
+ }
+ return layer.alert("异常:" + JSON.stringify(xhr));
+ }
+ });
+ }, 400);
+});
+
+// 绑定回车事件
+$('[name=name],[name=pwd]').bind('keypress', function(event){
+ if(event.keyCode == "13") {
+ $('.login-btn').click();
+ }
+});
+
+// 输入框获取焦点
+$("[name=name]").focus();
+
+// 打印信息
+var str = "This page is provided by Sa-Token, Please refer to: " + "http://sa-token.dev33.cn/";
+console.log(str);
diff --git a/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/templates/sa-login.html b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/templates/sa-login.html
new file mode 100644
index 00000000..ea2eee3c
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-sso1-server/src/main/resources/templates/sa-login.html
@@ -0,0 +1,45 @@
+
+
+
+ Sa-SSO-Server 认证中心-登录
+
+
+
+
+
+
+
+
+
+
+
+
+
Sa-SSO-Server 认证中心
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This page is provided by Sa-Token-SSO
+
+
+
+
+
+
+
+
+
+
diff --git a/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/SaSsoApplication.java b/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/SaSsoApplication.java
index c80e20a4..c8c33aa0 100644
--- a/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/SaSsoApplication.java
+++ b/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/SaSsoApplication.java
@@ -8,9 +8,29 @@ import cn.dev33.satoken.SaManager;
@SpringBootApplication
public class SaSsoApplication {
+ /*
+ 此 demo 意在使用最少的代码演示一下SSO模式一的认证原理
+ 1、改hosts(C:\windows\system32\drivers\etc\hosts)
+ 127.0.0.1 sso.stp.com
+ 127.0.0.1 s1.stp.com
+ 127.0.0.1 s2.stp.com
+ 127.0.0.1 s3.stp.com
+ 2、运行项目
+ 启动 SaSsoApplication
+ 3、浏览器访问
+ http://s1.stp.com:8081/sso/isLogin
+ http://s2.stp.com:8081/sso/isLogin
+ http://s3.stp.com:8081/sso/isLogin
+ 均显示未登录
+ 4、然后访问任意节点的登录接口:
+ http://s1.stp.com:8081/sso/doLogin
+ 5、重复步骤3,刷新三个地址
+ 均显示已登录
+ */
+
public static void main(String[] args) {
SpringApplication.run(SaSsoApplication.class, args);
System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
}
-
+
}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/sso/SsoController.java b/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/sso/SsoController.java
index d5e59d57..7ace8472 100644
--- a/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/sso/SsoController.java
+++ b/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/sso/SsoController.java
@@ -4,9 +4,8 @@ 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.StpUtil;
+import cn.dev33.satoken.util.SaResult;
/**
* 测试: 同域单点登录
@@ -15,21 +14,21 @@ import cn.dev33.satoken.stp.StpUtil;
@RestController
@RequestMapping("/sso/")
public class SsoController {
-
+
// 测试:进行登录
@RequestMapping("doLogin")
- public AjaxJson doLogin(@RequestParam(defaultValue = "10001") String id) {
+ public SaResult doLogin(@RequestParam(defaultValue = "10001") String id) {
System.out.println("---------------- 进行登录 ");
StpUtil.login(id);
- return AjaxJson.getSuccess("登录成功: " + id);
+ return SaResult.ok("登录成功: " + id);
}
// 测试:是否登录
@RequestMapping("isLogin")
- public AjaxJson isLogin() {
+ public SaResult isLogin() {
System.out.println("---------------- 是否登录 ");
boolean isLogin = StpUtil.isLogin();
- return AjaxJson.getSuccess("是否登录: " + isLogin);
+ return SaResult.ok("是否登录: " + isLogin);
}
}
diff --git a/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/util/AjaxJson.java b/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/util/AjaxJson.java
deleted file mode 100644
index 768d0578..00000000
--- a/sa-token-demo/sa-token-demo-sso1/src/main/java/com/pj/util/AjaxJson.java
+++ /dev/null
@@ -1,162 +0,0 @@
-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-doc/doc/sso/readme.md b/sa-token-doc/doc/sso/readme.md
index e1b5bc66..076fc699 100644
--- a/sa-token-doc/doc/sso/readme.md
+++ b/sa-token-doc/doc/sso/readme.md
@@ -1,11 +1,13 @@
# Sa-Token-SSO 单点登录模块
+凡是稍微上点规模的系统,统一认证中心都是绕不过去的槛。而单点登录——便是我们搭建统一认证中心的关键。
+
---
### 什么是单点登录?解决什么问题?
举个场景,假设我们的系统被切割为N个部分:商城、论坛、直播、社交…… 如果用户每访问一个模块都要登录一次,那么用户将会疯掉,
-为了优化用户体验,我们急需一套机制将这N个系统的认证授权互通共享,让用户在一个系统登录之后,便可以畅通无阻的访问其它所有系统
+为了优化用户体验,我们急需一套机制将这N个系统的认证授权互通共享,让用户在一个系统登录之后,便可以畅通无阻的访问其它所有系统。
单点登录——就是为了解决这个问题而生!
@@ -13,19 +15,19 @@
### 架构选型
-对于单点登录,网上教程大多以CAS模式为主,其实对于不同的系统架构,实现单点登录的步骤也大为不同,Sa-Token由简入难将其划分为三种模式:
+对于单点登录,网上教程大多以CAS模式为主,其实对于不同的系统架构,实现单点登录的步骤也大为不同,Sa-Token 由简入难将其划分为三种模式:
-| 系统架构 | 采用模式 | 简介 | 文档链接 |
-| :-------- | :-------- | :-------- | :-------- |
-| 前端同域 + 后端同 Redis | 模式一 | 共享Cookie同步会话 | [文档](/sso/sso-type1)、[示例](https://gitee.com/dromara/sa-token/blob/dev/sa-token-demo/sa-token-demo-sso1) |
-| 前端不同域 + 后端同 Redis | 模式二 | URL重定向传播会话 | [文档](/sso/sso-type2)、[示例](https://gitee.com/dromara/sa-token/blob/dev/sa-token-demo/sa-token-demo-sso2-server) |
-| 前端不同域 + 后端 不同Redis | 模式三 | Http请求获取会话 | [文档](/sso/sso-type3)、[示例](https://gitee.com/dromara/sa-token/blob/dev/sa-token-demo/sa-token-demo-sso3-server) |
+| 系统架构 | 采用模式 | 简介 | 文档链接 |
+| :-------- | :-------- | :-------- | :-------- |
+| 前端同域 + 后端同 Redis | 模式一 | 共享 Cookie 同步会话 | [文档](/sso/sso-type1)、[示例](https://gitee.com/dromara/sa-token/blob/dev/sa-token-demo/sa-token-demo-sso1) |
+| 前端不同域 + 后端同 Redis | 模式二 | URL重定向传播会话 | [文档](/sso/sso-type2)、[示例](https://gitee.com/dromara/sa-token/blob/dev/sa-token-demo/sa-token-demo-sso2-server) |
+| 前端不同域 + 后端不同 Redis | 模式三 | Http请求获取会话 | [文档](/sso/sso-type3)、[示例](https://gitee.com/dromara/sa-token/blob/dev/sa-token-demo/sa-token-demo-sso3-server) |
-1. 前端同域:就是指多个系统可以部署在同一个主域名之下,比如:`c1.domain.com`、`c2.domain.com`、`c3.domain.com`
-2. 后端同Redis:就是指多个系统可以连接同一个Redis,其它的缓存数据中心亦可。PS:这里并不需要把所有项目的数据都放在同一个Redis中,Sa-Token提供了 **`[权限缓存与业务缓存分离]`** 的解决方案,详情戳:[Alone独立Redis插件](http://sa-token.dev33.cn/doc/index.html#/plugin/alone-redis)
-3. 如果既无法做到前端同域,也无法做到后端同Redis,那么只能走模式三,Http请求获取会话(Sa-Token对SSO提供了完整的封装,你只需要按照示例从文档上复制几段代码便可以轻松集成)
-4. 技术选型一定要根据系统架构对症下药,切不可胡乱选择
+1. 前端同域:就是指多个系统可以部署在同一个主域名之下,比如:`c1.domain.com`、`c2.domain.com`、`c3.domain.com`。
+2. 后端同Redis:就是指多个系统可以连接同一个Redis,其它的缓存数据中心亦可。PS:这里并不需要把所有项目的数据都放在同一个Redis中,Sa-Token提供了 **`[权限缓存与业务缓存分离]`** 的解决方案,详情戳:[Alone独立Redis插件](http://sa-token.dev33.cn/doc/index.html#/plugin/alone-redis)。
+3. 如果既无法做到前端同域,也无法做到后端同Redis,那么只能走模式三,Http请求获取会话(Sa-Token对SSO提供了完整的封装,你只需要按照示例从文档上复制几段代码便可以轻松集成)。
+4. 技术选型一定要根据系统架构对症下药,切不可胡乱选择。
### Sa-Token-SSO 特性
diff --git a/sa-token-doc/doc/sso/sso-type1.md b/sa-token-doc/doc/sso/sso-type1.md
index dfa8cbbc..06065ff1 100644
--- a/sa-token-doc/doc/sso/sso-type1.md
+++ b/sa-token-doc/doc/sso/sso-type1.md
@@ -1,29 +1,29 @@
# SSO模式一 共享Cookie同步会话
-如果我们的多个系统可以做到:前端同域、后端同Redis,那么便可以使用 **`[共享Cookie同步会话]`** 的方式做到单点登录
+如果我们的多个系统可以做到:前端同域、后端同Redis,那么便可以使用 **`[共享Cookie同步会话]`** 的方式做到单点登录。
---
### 0、解决思路?
首先我们分析一下多个系统之间,为什么无法同步登录状态?
-1. 前端的`Token`无法在多个系统下共享
-2. 后端的`Session`无法在多个系统间共享
+1. 前端的`Token`无法在多个系统下共享。
+2. 后端的`Session`无法在多个系统间共享。
所以单点登录第一招,就是对症下药:
-1. 使用`共享Cookie`来解决Token共享问题
-2. 使用`Redis`来解决Session共享问题
+1. 使用`共享Cookie`来解决Token共享问题。
+2. 使用`Redis`来解决Session共享问题。
-所谓共享Cookie,就是主域名Cookie在二级域名下的共享,举个例子:写在父域名`stp.com`下的Cookie,在`s1.stp.com`、`s2.stp.com`等子域名都是可以共享访问的
+所谓共享Cookie,就是主域名Cookie在二级域名下的共享,举个例子:写在父域名`stp.com`下的Cookie,在`s1.stp.com`、`s2.stp.com`等子域名都是可以共享访问的。
-而共享Redis,并不需要我们把所有项目的数据都放在同一个Redis中,Sa-Token提供了 **[权限缓存与业务缓存分离]** 的解决方案,详情戳:[Alone独立Redis插件](/plugin/alone-redis)
+而共享Redis,并不需要我们把所有项目的数据都放在同一个Redis中,Sa-Token提供了 **[权限缓存与业务缓存分离]** 的解决方案,详情戳:[Alone独立Redis插件](/plugin/alone-redis)。
-> PS:这里建议不要用B项目去连接A项目的Redis,也不要A项目连接B项目的Redis,而是抽离出一个单独的 SSO-Redis,A 和 B 一起连接这个 SSO-Redis
+
-OK,所有理论就绪,下面开始实战
+OK,所有理论就绪,下面开始实战:
-> Sa-Token整合同域单点登录非常简单,相比于正常的登录,你只需增加配置 `sa-token.cookie-domain=xxx.com` 指定一下Cookie写入时的父级域名即可
-> 整合示例在官方仓库的 `/sa-token-demo/sa-token-demo-sso1/`,如遇到难点可结合源码进行测试学习
+> Sa-Token整合同域单点登录非常简单,相比于正常的登录,你只需增加配置 `sa-token.cookie-domain=xxx.com` 指定一下Cookie写入时的父级域名即可。
+> 整合示例在官方仓库的 `/sa-token-demo/sa-token-demo-sso1/`,如遇到难点可结合源码进行测试学习。
@@ -31,13 +31,17 @@ OK,所有理论就绪,下面开始实战
首先修改hosts文件`(C:\windows\system32\drivers\etc\hosts)`,添加以下IP映射,方便我们进行测试:
``` url
+127.0.0.1 sso.stp.com
127.0.0.1 s1.stp.com
127.0.0.1 s2.stp.com
127.0.0.1 s3.stp.com
```
+其中:`sso.stp.com`为统一认证地址,当用户在其它 Client 端发起登录请求时,均将其重定向至认证中心,待到登录成功之后再原路返回到 Client 端。
+
+
### 2、指定Cookie的作用域
-在`s1.stp.com`访问服务器,其Cookie也只能写入到`s1.stp.com`下,为了将Cookie写入到其父级域名`stp.com`下,我们需要新增配置:
+在`s1.stp.com`访问服务器,其Cookie也只能写入到`s1.stp.com`下,为了将Cookie写入到其父级域名`stp.com`下,我们需要新增配置:
``` yml
sa-token:
# 写入Cookie时显式指定的作用域, 用于单点登录二级域名共享Cookie
@@ -57,18 +61,18 @@ public class SsoController {
// 测试:进行登录
@RequestMapping("doLogin")
- public AjaxJson doLogin(@RequestParam(defaultValue = "10001") String id) {
+ public SaResult doLogin(@RequestParam(defaultValue = "10001") String id) {
System.out.println("---------------- 进行登录 ");
StpUtil.login(id);
- return AjaxJson.getSuccess("登录成功: " + id);
+ return SaResult.ok("登录成功: " + id);
}
// 测试:是否登录
@RequestMapping("isLogin")
- public AjaxJson isLogin() {
+ public SaResult isLogin() {
System.out.println("---------------- 是否登录 ");
boolean isLogin = StpUtil.isLogin();
- return AjaxJson.getSuccess("是否登录: " + isLogin);
+ return SaResult.ok("是否登录: " + isLogin);
}
}
@@ -104,10 +108,48 @@ public class SaSsoApplication {

-测试完毕
+测试完毕!
-### 5、跨域模式下的解决方案
+### 5、搭建统一认证中心
+
+上面的示例,我们简单的演示了SSO模式一的认证原理。
+
+当然,在实际的正式项目中,我们肯定不会每个系统都内置一个登录接口,一般的做法是搭建一个独立的SSO认证中心,我们所有 Client 端的登录请求都会被重定向至认证中心,
+待到登录成功之后再原路返回到 Client 端。
+
+我们可以运行一下官方仓库的示例,里面有制作好的登录页面
+
+> 下载官方示例,依次运行:
+> - `/sa-token-demo/sa-token-demo-sso1-server/`
+> - `/sa-token-demo/sa-token-demo-sso1-client/`
+
+
+访问三个应用端:
+- [http://s1.stp.com:9001/](http://s1.stp.com:9001/)
+- [http://s2.stp.com:9001/](http://s2.stp.com:9001/)
+- [http://s3.stp.com:9001/](http://s3.stp.com:9001/)
+
+均返回:
+
+
+
+然后点击登录,被重定向至SSO认证中心:
+
+
+
+输入默认测试账号:`sa / 123456`,点击登录
+
+
+
+刷新另外两个Client端,均显示已登录
+
+
+
+测试完成
+
+
+### 6、跨域模式下的解决方案
如上,我们使用极其简单的步骤实现了同域下的单点登录,聪明如你😏,马上想到了这种模式有着一个不小的限制:
diff --git a/sa-token-doc/doc/sso/sso-type2.md b/sa-token-doc/doc/sso/sso-type2.md
index 7d9f9bf0..ba57f081 100644
--- a/sa-token-doc/doc/sso/sso-type2.md
+++ b/sa-token-doc/doc/sso/sso-type2.md
@@ -306,7 +306,12 @@ public class SaSsoClientApplication {
以上示例,虽然完整的复现了单点登录的过程,但是页面还是有些简陋,我们可以运行一下官方仓库的示例,里面有制作好的登录页面
-> 下载官方示例,依次运行 `/sa-token-demo/sa-token-demo-sso-client/` 和 `/sa-token-demo/sa-token-demo-sso-server/`,访问:[http://sa-sso-client1.com:9001/](http://sa-sso-client1.com:9001/)
+> 下载官方示例,依次运行:
+> - `/sa-token-demo/sa-token-demo-sso2-server/`
+> - `/sa-token-demo/sa-token-demo-sso2-client/`
+>
+> 然后访问:
+> - [http://sa-sso-client1.com:9001/](http://sa-sso-client1.com:9001/)

diff --git a/sa-token-doc/doc/start/download.md b/sa-token-doc/doc/start/download.md
index d193795d..5d849bd0 100644
--- a/sa-token-doc/doc/start/download.md
+++ b/sa-token-doc/doc/start/download.md
@@ -106,7 +106,9 @@ implementation 'cn.dev33:sa-token-core:${sa.top.version}'
├── sa-token-demo-solon // [示例] Sa-Token 集成 Solon
├── sa-token-demo-quick-login // [示例] Sa-Token 集成 quick-login 模块
├── sa-token-demo-alone-redis // [示例] Sa-Token 集成 alone-redis 模块
- ├── sa-token-demo-sso1 // [示例] Sa-Token 集成 SSO单点登录-模式一
+ ├── sa-token-demo-sso1 // [示例] Sa-Token 集成 SSO单点登录-模式一简单测试
+ ├── sa-token-demo-sso1-server // [示例] Sa-Token 集成 SSO单点登录-模式一 认证中心
+ ├── sa-token-demo-sso1-client // [示例] Sa-Token 集成 SSO单点登录-模式一 应用端
├── sa-token-demo-sso2-server // [示例] Sa-Token 集成 SSO单点登录-模式二 认证中心
├── sa-token-demo-sso2-client // [示例] Sa-Token 集成 SSO单点登录-模式二 应用端
├── sa-token-demo-sso3-server // [示例] Sa-Token 集成 SSO单点登录-模式三 认证中心