list = Arrays.asList(10041, 10042, 10043, 10044);
// 返回
return list;
}
```
#### 4.3、访问测试
访问测试:[http://sa-sso-client1.com:9001/sso/myFansList](http://sa-sso-client1.com:9001/sso/myFansList)
### 5、无刷单点注销
有了单点登录,就必然伴随着单点注销(一处注销,全端下线)
此处简单介绍一下 SSO 模式三的单点注销链路过程:
1. sso-client 端在校验 ticket 时(调用 `http://{sso-server}/sso/checkTicket` 时),将注销回调地址 `http://{sso-client}/sso/logoutCall` 发送到 Server 端。
2. sso-server 端将此 sso-client 的注销回调地址以 List 集合的形式存储在该账号 Access-Session 的 dataMap。
3. sso-client 的前端向 sso-client 的后端发起单点注销请求。(调用 `http://{sso-client}/sso/logout`)
4. sso-client 的后端向 sso-server 的后端发送单点注销请求。(调用 `http://{sso-server}/sso/signout`)
5. sso-server 端遍历该账号 Access-Session 存储的注销回调地址集合,逐个通知 sso-client 端下线。(`http://{sso-client}/sso/logoutCall`)
6. sso-server 端注销下线。
7. sso-server 后端响应 sso-client 后端:注销完成。
7. sso-client 后端响应 sso-client 前端:注销完成。
8. 整体完成。
这些逻辑 Sa-Token 内部已经封装完毕,你只需按照文档步骤集成即可。
#### 5.1、更改注销方案
将 sso-client 首页路由方法里的注销链接换成 `/sso/logout` 接口:
``` java
// SSO-Client端:首页
@RequestMapping("/")
public String index() {
String str = "Sa-Token SSO-Client 应用端
" +
"当前会话是否登录:" + StpUtil.isLogin() + "
" +
"登录" +
" 注销
";
return str;
}
```
#### 5.2、启动测试
重启项目,依次登录三个 client:
- [http://sa-sso-client1.com:9001/](http://sa-sso-client1.com:9001/)
- [http://sa-sso-client2.com:9001/](http://sa-sso-client2.com:9001/)
- [http://sa-sso-client3.com:9001/](http://sa-sso-client3.com:9001/)

在任意一个 client 里,点击 **`[注销]`** 按钮,即可单点注销成功(打开另外两个client,刷新一下页面,登录态丢失)。

PS:这里我们为了方便演示,使用的是超链接跳页面的形式,正式项目中使用 Ajax 调用接口即可做到无刷单点登录退出。
例如,我们使用 [Apifox 接口测试工具](https://www.apifox.cn/) 可以做到同样的效果:

测试完毕!
### 6、后记
当我们熟读三种模式的单点登录之后,其实不难发现:所谓单点登录,其本质就是多个系统之间的会话共享。
当我们理解这一点之后,三种模式的工作原理也浮出水面:
- 模式一:采用共享 Cookie 来做到前端 Token 的共享,从而达到后端的 Session 会话共享。
- 模式二:采用 URL 重定向,以 ticket 码为授权中介,做到多个系统间的会话传播。
- 模式三:采用 Http 请求主动查询会话,做到 Client 端与 Server 端的会话同步。