sa-token/sa-token-doc/sso/sso-type1.md

272 lines
8.4 KiB
Markdown
Raw Normal View History

2021-06-26 23:30:29 +08:00
# SSO模式一 共享Cookie同步会话
2021-08-26 23:17:39 +08:00
如果我们的多个系统可以做到前端同域、后端同Redis那么便可以使用 **`[共享Cookie同步会话]`** 的方式做到单点登录。
2021-06-26 23:30:29 +08:00
---
### 1、解决思路
2021-06-26 23:30:29 +08:00
2021-06-29 23:32:35 +08:00
首先我们分析一下多个系统之间,为什么无法同步登录状态?
1. 前端的 `Token` 无法在多个系统下共享。
2. 后端的 `Session` 无法在多个系统间共享。
2021-06-26 23:30:29 +08:00
所以单点登录第一招,就是对症下药:
1. 使用 `共享Cookie` 来解决 Token 共享问题。
2. 使用 `Redis` 来解决 Session 共享问题。
2021-06-26 23:30:29 +08:00
2021-08-26 23:17:39 +08:00
所谓共享Cookie就是主域名Cookie在二级域名下的共享举个例子写在父域名`stp.com`下的Cookie在`s1.stp.com`、`s2.stp.com`等子域名都是可以共享访问的。
2021-06-26 23:30:29 +08:00
2021-08-26 23:17:39 +08:00
而共享Redis并不需要我们把所有项目的数据都放在同一个Redis中Sa-Token提供了 **[权限缓存与业务缓存分离]** 的解决方案,详情戳:[Alone独立Redis插件](/plugin/alone-redis)。
2021-06-26 23:30:29 +08:00
2022-05-09 17:35:29 +08:00
<button class="show-img" img-src="https://oss.dev33.cn/sa-token/doc/g/g3--sso1.gif">加载动态演示图</button>
2021-08-26 23:17:39 +08:00
OK所有理论就绪下面开始实战
2021-06-26 23:30:29 +08:00
2021-07-08 01:24:42 +08:00
### 2、准备工作
2021-06-26 23:30:29 +08:00
2021-07-19 01:12:55 +08:00
首先修改hosts文件`(C:\windows\system32\drivers\etc\hosts)`添加以下IP映射方便我们进行测试
``` url
2021-08-26 23:17:39 +08:00
127.0.0.1 sso.stp.com
2021-06-26 23:30:29 +08:00
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 端。
2021-08-26 23:17:39 +08:00
### 3、指定Cookie的作用域
在`sso.stp.com`访问服务器其Cookie也只能写入到`sso.stp.com`下为了将Cookie写入到其父级域名`stp.com`下,我们需要更改 SSO-Server 端的 yml 配置:
2021-08-26 23:17:39 +08:00
<!---------------------------- tabs:start ---------------------------->
<!------------- tab:yaml 风格 ------------->
``` yaml
sa-token:
cookie:
# 配置 Cookie 作用域
domain: stp.com
```
<!------------- tab:properties 风格 ------------->
``` properties
# 配置 Cookie 作用域
sa-token.cookie.domain=stp.com
2021-06-26 23:30:29 +08:00
```
<!---------------------------- tabs:end ---------------------------->
2021-06-26 23:30:29 +08:00
2021-10-11 01:09:28 +08:00
这个配置原本是被注释掉的,现在将其打开。另外我们格外需要注意:
在SSO模式一测试完毕之后一定要将这个配置再次注释掉因为模式一与模式二三使用不同的授权流程这行配置会影响到我们模式二和模式三的正常运行。
2021-06-26 23:30:29 +08:00
2021-06-29 23:32:35 +08:00
### 4、搭建 Client 端项目
2021-06-26 23:30:29 +08:00
2021-10-11 01:09:28 +08:00
> 搭建示例在官方仓库的 `/sa-token-demo/sa-token-demo-sso1-client/`,如遇到难点可结合源码进行测试学习。
2021-06-26 23:30:29 +08:00
#### 4.1、引入依赖
新建项目 sa-token-demo-sso1-client并添加以下依赖
2021-06-29 23:32:35 +08:00
<!---------------------------- tabs:start ---------------------------->
<!-------- tab:Maven 方式 -------->
``` xml
2022-10-21 11:27:29 +08:00
<!-- Sa-Token 权限认证, 在线文档https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa.top.version}</version>
</dependency>
2022-05-06 10:31:46 +08:00
<!-- Sa-Token 插件整合SSO -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-sso</artifactId>
<version>${sa.top.version}</version>
</dependency>
2021-06-26 23:30:29 +08:00
<!-- Sa-Token 整合redis (使用jackson序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>${sa.top.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2021-06-29 23:32:35 +08:00
<!-- Sa-Token插件权限缓存与业务缓存分离 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-alone-redis</artifactId>
<version>${sa.top.version}</version>
</dependency>
```
<!-------- tab:Gradle 方式 -------->
``` gradle
2022-10-21 11:27:29 +08:00
// Sa-Token 权限认证在线文档https://sa-token.cc
implementation 'cn.dev33:sa-token-spring-boot-starter:${sa.top.version}'
// Sa-Token 插件整合SSO
implementation 'cn.dev33:sa-token-sso:${sa.top.version}'
// Sa-Token 整合 Redis (使用 jackson 序列化方式)
implementation 'cn.dev33:sa-token-dao-redis-jackson:${sa.top.version}'
implementation 'org.apache.commons:commons-pool2'
// Sa-Token插件权限缓存与业务缓存分离
implementation 'cn.dev33:sa-token-alone-redis:${sa.top.version}'
```
<!---------------------------- tabs:end ---------------------------->
2021-06-26 23:30:29 +08:00
2021-08-26 23:17:39 +08:00
#### 4.2、新建 Controller 控制器
2021-08-26 23:17:39 +08:00
``` java
/**
* Sa-Token-SSO Client端 Controller
* @author kong
*/
@RestController
public class SsoClientController {
// SSO-Client端首页
@RequestMapping("/")
public String index() {
2022-08-20 12:05:36 +08:00
String authUrl = SaSsoManager.getConfig().splicingAuthUrl();
String solUrl = SaSsoManager.getConfig().splicingSloUrl();
String str = "<h2>Sa-Token SSO-Client 应用端</h2>" +
"<p>当前会话是否登录:" + StpUtil.isLogin() + "</p>" +
"<p><a href=\"javascript:location.href='" + authUrl + "?mode=simple&redirect=' + encodeURIComponent(location.href);\">登录</a> " +
"<a href=\"javascript:location.href='" + solUrl + "?back=' + encodeURIComponent(location.href);\">注销</a> </p>";
return str;
}
// 全局异常拦截
@ExceptionHandler
public SaResult handlerException(Exception e) {
e.printStackTrace();
return SaResult.error(e.getMessage());
}
}
```
2021-08-26 23:17:39 +08:00
#### 4.3、application.yml 配置
2021-08-26 23:17:39 +08:00
<!---------------------------- tabs:start ---------------------------->
<!------------- tab:yaml 风格 ------------->
``` yaml
# 端口
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
```
<!------------- tab:properties 风格 ------------->
``` properties
# 端口
server.port=9001
######### Sa-Token 配置 #########
# SSO-Server端-单点登录授权地址
sa-token.sso.auth-url=http://sso.stp.com:9000/sso/auth
# SSO-Server端-单点注销地址
sa-token.sso.slo-url=http://sso.stp.com:9000/sso/logout
# 配置 Sa-Token 单独使用的Redis连接 此处需要和SSO-Server端连接同一个Redis
# Redis数据库索引
sa-token.alone-redis.database=1
# Redis服务器地址
sa-token.alone-redis.host=127.0.0.1
# Redis服务器连接端口
sa-token.alone-redis.port=6379
# Redis服务器连接密码默认为空
sa-token.alone-redis.password=
# 连接超时时间
sa-token.alone-redis.timeout=10s
```
<!---------------------------- tabs:end ---------------------------->
2021-08-26 23:17:39 +08:00
#### 4.4、启动类
2021-08-26 23:17:39 +08:00
``` java
/**
* SSO模式一Client端 Demo
*/
@SpringBootApplication
public class SaSsoClientApplication {
public static void main(String[] args) {
SpringApplication.run(SaSsoClientApplication.class, args);
System.out.println("\nSa-Token SSO模式一 Client端启动成功");
}
}
```
2021-08-26 23:17:39 +08:00
### 5、访问测试
启动项目,依次访问三个应用端:
2021-08-26 23:17:39 +08:00
- [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/)
2021-08-26 23:17:39 +08:00
均返回:
![sso1--index.png](https://oss.dev33.cn/sa-token/doc/sso/sso1--index.png 's-w-sh')
然后点击登录被重定向至SSO认证中心
![sso1--login-page2.png](https://oss.dev33.cn/sa-token/doc/sso/sso1--login-page2.png 's-w-sh')
2021-08-26 23:17:39 +08:00
我们点击登录,然后刷新页面:
2021-08-26 23:17:39 +08:00
![sso1-login-ok.png](https://oss.dev33.cn/sa-token/doc/sso/sso1-login-ok.png 's-w-sh')
刷新另外两个Client端均显示已登录
![sso1-login-ok2.png](https://oss.dev33.cn/sa-token/doc/sso/sso1-login-ok2.png 's-w-sh')
测试完成
2021-06-26 23:30:29 +08:00
2021-08-26 23:17:39 +08:00
### 6、跨域模式下的解决方案
2021-06-26 23:30:29 +08:00
如上,我们使用简单的步骤实现了同域下的单点登录,聪明如你😏,马上想到了这种模式有着一个不小的限制:
2021-06-26 23:30:29 +08:00
> 所有子系统的域名,必须同属一个父级域名
如果我们的子系统在完全不同的域名下,我们又该怎么完成单点登录功能呢?
且往下看,[SSO模式二URL重定向传播会话](/sso/sso-type2)