sa-token-doc/sso/signout.md
Sa-Token SSO 提供多种注销模式:
从注销范围上可以分为:
从注销方式上可以分为:
在后端添加接口:
// 当前应用独自注销 (不退出其它应用)
@RequestMapping("/sso/logoutByAlone")
public Object logoutByAlone() {
StpUtil.logout();
return SaSsoClientProcessor.instance._ssoLogoutBack(SaHolder.getRequest(), SaHolder.getResponse());
}
在前端或跳转或 ajax 异步调用此接口即可。
如果是跳转可指定 back 参数,代表注销成功后跳转的地址,例如:http://sso-client.com/sso/logoutByAlone?back=https://sa-token.cc
此处先简单看一下 Sa-Token SSO 的单点注销链路过程:
http://{sso-client}/sso/logout)http://{sso-server}/sso/pushS?msgType=signout)http://{sso-client}/sso/pushC?msgType=logoutCall)<button class="show-img" img-src="/big-file/doc/sso/g3--sso3-logout.gif">加载动态演示图</button>
这些逻辑 Sa-Token 内部已经封装完毕,你只需按照文档步骤集成即可。以模式三 demo 为例:
单点注销是 Sa-Token SSO 内部已封装的接口,无需手动再添加,只需要在前端调用即可。
// SSO-Client端:首页
@RequestMapping("/")
public String index() {
String str = "<h2>Sa-Token SSO-Client 应用端 (模式三)</h2>" +
"<p>当前会话是否登录:" + StpUtil.isLogin() + " (" + StpUtil.getLoginId("") + ")</p>" +
"<p> " +
"<a href='/sso/login?back=/'>登录</a> - " +
"<a href='/sso/logoutByAlone?back=/'>单应用注销</a> - " +
"<a href='/sso/logout?back=self'>全端注销</a> " +
"</p>";
return str;
}
重点在第 9 行。
重启项目,依次登录三个 client:
在任意一个 client 里,点击 [注销] 按钮,即可单点注销成功(打开另外两个client,刷新一下页面,登录态丢失)。
PS:这里我们为了方便演示,使用的是超链接跳页面的形式,正式项目中使用 Ajax 调用接口即可做到无刷单点登录退出。
例如,我们使用 Apifox 接口测试工具 可以做到同样的效果:
单浏览器注销的前提是在登录时按照 deviceId 设备ID 参数为登录进行分组,这样在发起注销时即可格局设备ID参数做到单浏览器注销功能。
首先在 sso-server 的登录方法内,加上 deviceId 参数,例如:
@RestController
public class SsoServerController {
// 其它代码,非重点,省略展示...
// 配置SSO相关参数
@Autowired
private void configSso(SaSsoServerTemplate ssoServerTemplate) {
// 配置:登录处理函数
ssoServerTemplate.strategy.doLoginHandle = (name, pwd) -> {
// 此处仅做模拟登录,真实环境应该查询数据库进行登录
if("sa".equals(name) && "123456".equals(pwd)) {
String deviceId = SaHolder.getRequest().getParam("deviceId", SaFoxUtil.getRandomString(32));
StpUtil.login(10001, new SaLoginParameter().setDeviceId(deviceId));
return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue());
}
return SaResult.error("登录失败!");
};
}
}
如上代码,在登录时获取前端提交的 deviceId 参数,如果前端没有提交则随机生成一个。
然后在 sso-client 发起单点注销时,加上 singleDeviceIdLogout=true 参数,代表按照设备 id 进行分组注销,非本设备id的会话不参与注销行为:
// SSO-Client端:首页
@RequestMapping("/")
public String index() {
String str = "<h2>Sa-Token SSO-Client 应用端 (模式三)</h2>" +
"<p>当前会话是否登录:" + StpUtil.isLogin() + " (" + StpUtil.getLoginId("") + ")</p>" +
"<p> " +
"<a href='/sso/login?back=/'>登录</a> - " +
"<a href='/sso/logoutByAlone?back=/'>单应用注销</a> - " +
"<a href='/sso/logout?back=self&singleDeviceIdLogout=true'>单浏览器注销</a> - " +
"<a href='/sso/logout?back=self'>全端注销</a> " +
"</p>";
return str;
}
重点在第 9 行。
[!WARNING| label:测试注意点] 在进行测试时,同时将一个浏览器双击打开两次,是不算 “不同浏览器” 的,虽然你打开了两个浏览器窗口,但是这两个浏览器的会话数据是互通的。
必须打开两个不同的浏览器来测试,或者按快捷键
ctrl + shift + N打开隐私模式,才可以做到会话相互隔离。