mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-06-28 13:34:18 +08:00
feat(sso): 单点注销支持单设备注销
This commit is contained in:
parent
c2dea166e4
commit
5aac119beb
@ -34,7 +34,7 @@ public class H5Controller {
|
|||||||
return SaResult.data(redirect);
|
return SaResult.data(redirect);
|
||||||
} else {
|
} else {
|
||||||
// 模式二或模式三
|
// 模式二或模式三
|
||||||
String redirectUrl = SaSsoUtil.buildRedirectUrl(StpUtil.getLoginId(), client, redirect);
|
String redirectUrl = SaSsoUtil.buildRedirectUrl(client, redirect, StpUtil.getLoginId(), StpUtil.getLoginDeviceId());
|
||||||
return SaResult.data(redirectUrl);
|
return SaResult.data(redirectUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import cn.dev33.satoken.sign.SaSignUtil;
|
|||||||
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
|
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
|
||||||
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
|
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||||
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@ -44,7 +46,8 @@ public class SsoServerController {
|
|||||||
ssoServer.doLoginHandle = (name, pwd) -> {
|
ssoServer.doLoginHandle = (name, pwd) -> {
|
||||||
// 此处仅做模拟登录,真实环境应该查询数据进行登录
|
// 此处仅做模拟登录,真实环境应该查询数据进行登录
|
||||||
if("sa".equals(name) && "123456".equals(pwd)) {
|
if("sa".equals(name) && "123456".equals(pwd)) {
|
||||||
StpUtil.login(10001);
|
String deviceId = SaHolder.getRequest().getParam("deviceId", SaFoxUtil.getRandomString(32));
|
||||||
|
StpUtil.login(10001, SaLoginParameter.create().setDeviceId(deviceId));
|
||||||
return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue());
|
return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue());
|
||||||
}
|
}
|
||||||
return SaResult.error("登录失败!");
|
return SaResult.error("登录失败!");
|
||||||
|
@ -25,6 +25,7 @@ import cn.dev33.satoken.sso.template.SaSsoClientTemplate;
|
|||||||
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
||||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,9 +65,12 @@ public class SaSsoMessageLogoutCallHandle implements SaSsoMessageHandle {
|
|||||||
|
|
||||||
// 获取参数
|
// 获取参数
|
||||||
String loginId = req.getParamNotNull(paramName.loginId);
|
String loginId = req.getParamNotNull(paramName.loginId);
|
||||||
|
String deviceId = message.getString(paramName.deviceId);
|
||||||
|
|
||||||
// 注销当前应用端会话
|
// 注销当前应用端会话
|
||||||
stpLogic.logout(loginId);
|
stpLogic.logout(loginId, new SaLogoutParameter()
|
||||||
|
.setDeviceId(deviceId)
|
||||||
|
);
|
||||||
|
|
||||||
// 响应
|
// 响应
|
||||||
return SaResult.ok("单点注销回调成功");
|
return SaResult.ok("单点注销回调成功");
|
||||||
|
@ -18,15 +18,15 @@ package cn.dev33.satoken.sso.message.handle.server;
|
|||||||
|
|
||||||
import cn.dev33.satoken.context.SaHolder;
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
import cn.dev33.satoken.context.model.SaRequest;
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
import cn.dev33.satoken.sso.SaSsoManager;
|
|
||||||
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
|
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
|
||||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||||
import cn.dev33.satoken.sso.message.handle.SaSsoMessageHandle;
|
import cn.dev33.satoken.sso.message.handle.SaSsoMessageHandle;
|
||||||
|
import cn.dev33.satoken.sso.model.TicketModel;
|
||||||
import cn.dev33.satoken.sso.name.ParamName;
|
import cn.dev33.satoken.sso.name.ParamName;
|
||||||
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
||||||
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
||||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,10 +60,12 @@ public class SaSsoMessageCheckTicketHandle implements SaSsoMessageHandle {
|
|||||||
// 1、获取参数
|
// 1、获取参数
|
||||||
SaRequest req = SaHolder.getRequest();
|
SaRequest req = SaHolder.getRequest();
|
||||||
SaSsoServerConfig ssoServerConfig = ssoServerTemplate.getServerConfig();
|
SaSsoServerConfig ssoServerConfig = ssoServerTemplate.getServerConfig();
|
||||||
|
StpLogic stpLogic = ssoServerTemplate.getStpLogic();
|
||||||
String client = req.getParam(paramName.client);
|
String client = req.getParam(paramName.client);
|
||||||
String ticket = req.getParamNotNull(paramName.ticket);
|
String ticket = req.getParamNotNull(paramName.ticket);
|
||||||
String sloCallback = req.getParam(paramName.ssoLogoutCall);
|
String sloCallback = req.getParam(paramName.ssoLogoutCall);
|
||||||
|
|
||||||
|
|
||||||
// 2、校验提供的client是否为非法字符
|
// 2、校验提供的client是否为非法字符
|
||||||
if(SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
if(SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
||||||
return SaResult.error("无效 client 标识:" + client);
|
return SaResult.error("无效 client 标识:" + client);
|
||||||
@ -77,17 +79,21 @@ public class SaSsoMessageCheckTicketHandle implements SaSsoMessageHandle {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 4、校验ticket,获取 loginId
|
// 4、校验ticket,获取 loginId
|
||||||
Object loginId = ssoServerTemplate.checkTicket(ticket, client);
|
TicketModel ticketModel = ssoServerTemplate.checkTicketParamAndDelete(ticket, client);
|
||||||
if(SaFoxUtil.isEmpty(loginId)) {
|
Object loginId = ticketModel.getLoginId();
|
||||||
return SaResult.error("无效ticket:" + ticket);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5、注册此客户端的单点注销回调URL
|
// 5、注册此客户端的单点注销回调URL
|
||||||
ssoServerTemplate.registerSloCallbackUrl(loginId, client, sloCallback);
|
ssoServerTemplate.registerSloCallbackUrl(loginId, client, sloCallback);
|
||||||
|
|
||||||
// 6、给 client 端响应结果
|
// 6、给 client 端响应结果
|
||||||
long remainSessionTimeout = ssoServerTemplate.getStpLogic().getSessionTimeoutByLoginId(loginId);
|
SaResult result = SaResult.ok();
|
||||||
SaResult result = SaResult.data(loginId).set(paramName.remainSessionTimeout, remainSessionTimeout);
|
result.setData(loginId); // 兼容历史版本
|
||||||
|
result.set(paramName.loginId, loginId);
|
||||||
|
result.set(paramName.tokenValue, ticketModel.getTokenValue());
|
||||||
|
result.set(paramName.deviceId, stpLogic.getLoginDeviceIdByToken(ticketModel.getTokenValue()));
|
||||||
|
result.set(paramName.remainTokenTimeout, stpLogic.getTokenTimeout(ticketModel.getTokenValue()));
|
||||||
|
result.set(paramName.remainSessionTimeout, stpLogic.getSessionTimeoutByLoginId(loginId));
|
||||||
|
|
||||||
result = ssoServerConfig.checkTicketAppendData.apply(loginId, result);
|
result = ssoServerConfig.checkTicketAppendData.apply(loginId, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import cn.dev33.satoken.sso.name.ParamName;
|
|||||||
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
||||||
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
||||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,9 +62,12 @@ public class SaSsoMessageSignoutHandle implements SaSsoMessageHandle {
|
|||||||
// 获取参数
|
// 获取参数
|
||||||
SaRequest req = SaHolder.getRequest();
|
SaRequest req = SaHolder.getRequest();
|
||||||
String loginId = req.getParam(paramName.loginId);
|
String loginId = req.getParam(paramName.loginId);
|
||||||
|
String deviceId = req.getParam(paramName.deviceId);
|
||||||
|
|
||||||
// step.2 单点注销
|
// step.2 单点注销
|
||||||
ssoServerTemplate.ssoLogout(loginId);
|
SaLogoutParameter logoutParameter = ssoServerTemplate.getStpLogic().createSaLogoutParameter()
|
||||||
|
.setDeviceId(deviceId);
|
||||||
|
ssoServerTemplate.ssoLogout(loginId, logoutParameter);
|
||||||
|
|
||||||
// 响应
|
// 响应
|
||||||
return SaResult.ok();
|
return SaResult.ok();
|
||||||
|
@ -32,21 +32,31 @@ public class SaCheckTicketResult implements Serializable {
|
|||||||
/** 账号id */
|
/** 账号id */
|
||||||
public Object loginId;
|
public Object loginId;
|
||||||
|
|
||||||
|
/** 在 sso-server 端的 token 值 */
|
||||||
|
public String tokenValue;
|
||||||
|
|
||||||
|
/** 登录设备 id */
|
||||||
|
public String deviceId;
|
||||||
|
|
||||||
|
/** 此账号 token 剩余有效期 */
|
||||||
|
public Long remainTokenTimeout;
|
||||||
|
|
||||||
/** 此账号会话剩余有效期 */
|
/** 此账号会话剩余有效期 */
|
||||||
public long remainSessionTimeout;
|
public Long remainSessionTimeout;
|
||||||
|
|
||||||
/** 从 sso-server 返回的所有参数 */
|
/** 从 sso-server 返回的所有参数 */
|
||||||
public SaResult result;
|
public SaResult result;
|
||||||
|
|
||||||
public SaCheckTicketResult(Object loginId, long remainSessionTimeout, SaResult result) {
|
public SaCheckTicketResult() {
|
||||||
this.loginId = loginId;
|
|
||||||
this.remainSessionTimeout = remainSessionTimeout;
|
|
||||||
this.result = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "CheckTicketResult{" +
|
return "SaCheckTicketResult{" +
|
||||||
"loginId=" + loginId +
|
"loginId=" + loginId +
|
||||||
|
", tokenValue='" + tokenValue + '\'' +
|
||||||
|
", deviceId='" + deviceId + '\'' +
|
||||||
|
", remainTokenTimeout=" + remainTokenTimeout +
|
||||||
", remainSessionTimeout=" + remainSessionTimeout +
|
", remainSessionTimeout=" + remainSessionTimeout +
|
||||||
", result=" + result +
|
", result=" + result +
|
||||||
'}';
|
'}';
|
||||||
|
@ -37,16 +37,21 @@ public class TicketModel implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public String client;
|
public String client;
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 设备 id
|
// * 设备 id
|
||||||
*/
|
// */
|
||||||
public String deviceId;
|
// public String deviceId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对应 loginId
|
* 对应 loginId
|
||||||
*/
|
*/
|
||||||
public Object loginId;
|
public Object loginId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话 token
|
||||||
|
*/
|
||||||
|
public String tokenValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间,13位时间戳
|
* 创建时间,13位时间戳
|
||||||
*/
|
*/
|
||||||
@ -64,14 +69,14 @@ public class TicketModel implements Serializable {
|
|||||||
* @param ticket 授权码
|
* @param ticket 授权码
|
||||||
* @param client 应用id
|
* @param client 应用id
|
||||||
* @param loginId 对应的账号id
|
* @param loginId 对应的账号id
|
||||||
* @param deviceId 重定向地址
|
* @param tokenValue 会话 token
|
||||||
*/
|
*/
|
||||||
public TicketModel(String ticket, String client, String deviceId, Object loginId) {
|
public TicketModel(String ticket, String client, Object loginId, String tokenValue) {
|
||||||
this();
|
this();
|
||||||
this.ticket = ticket;
|
this.ticket = ticket;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.deviceId = deviceId;
|
|
||||||
this.loginId = loginId;
|
this.loginId = loginId;
|
||||||
|
this.tokenValue = tokenValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -117,26 +122,6 @@ public class TicketModel implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 设备 id
|
|
||||||
*
|
|
||||||
* @return /
|
|
||||||
*/
|
|
||||||
public String getDeviceId() {
|
|
||||||
return this.deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置 设备 id
|
|
||||||
*
|
|
||||||
* @param deviceId /
|
|
||||||
* @return 对象自身
|
|
||||||
*/
|
|
||||||
public TicketModel setDeviceId(String deviceId) {
|
|
||||||
this.deviceId = deviceId;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 对应 loginId
|
* 获取 对应 loginId
|
||||||
*
|
*
|
||||||
@ -157,6 +142,26 @@ public class TicketModel implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 会话 token
|
||||||
|
*
|
||||||
|
* @return tokenValue 会话 token
|
||||||
|
*/
|
||||||
|
public String getTokenValue() {
|
||||||
|
return this.tokenValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 会话 token
|
||||||
|
*
|
||||||
|
* @param tokenValue 会话 token
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public TicketModel setTokenValue(String tokenValue) {
|
||||||
|
this.tokenValue = tokenValue;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 创建时间,13位时间戳
|
* 获取 创建时间,13位时间戳
|
||||||
*
|
*
|
||||||
@ -182,8 +187,8 @@ public class TicketModel implements Serializable {
|
|||||||
return "TicketModel{" +
|
return "TicketModel{" +
|
||||||
"ticket='" + ticket + '\'' +
|
"ticket='" + ticket + '\'' +
|
||||||
", client='" + client + '\'' +
|
", client='" + client + '\'' +
|
||||||
", deviceId='" + deviceId + '\'' +
|
|
||||||
", loginId=" + loginId +
|
", loginId=" + loginId +
|
||||||
|
", tokenValue=" + tokenValue +
|
||||||
", createTime=" + createTime +
|
", createTime=" + createTime +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,12 @@ public class ParamName {
|
|||||||
/** client参数名称 */
|
/** client参数名称 */
|
||||||
public String client = "client";
|
public String client = "client";
|
||||||
|
|
||||||
|
/** tokenValue 参数 */
|
||||||
|
public String tokenValue = "tokenValue";
|
||||||
|
|
||||||
|
/** deviceId 参数名称 */
|
||||||
|
public String deviceId = "deviceId";
|
||||||
|
|
||||||
/** secretkey参数名称 */
|
/** secretkey参数名称 */
|
||||||
public String secretkey = "secretkey";
|
public String secretkey = "secretkey";
|
||||||
|
|
||||||
@ -60,4 +66,10 @@ public class ParamName {
|
|||||||
/** Session 剩余有效期 参数名称 */
|
/** Session 剩余有效期 参数名称 */
|
||||||
public String remainSessionTimeout = "remainSessionTimeout";
|
public String remainSessionTimeout = "remainSessionTimeout";
|
||||||
|
|
||||||
|
/** token 剩余有效期 参数名称 */
|
||||||
|
public String remainTokenTimeout = "remainTokenTimeout";
|
||||||
|
|
||||||
|
/** singleDeviceIdLogout 参数 */
|
||||||
|
public String singleDeviceIdLogout = "singleDeviceIdLogout";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,14 @@ import cn.dev33.satoken.sso.error.SaSsoErrorCode;
|
|||||||
import cn.dev33.satoken.sso.exception.SaSsoException;
|
import cn.dev33.satoken.sso.exception.SaSsoException;
|
||||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||||
import cn.dev33.satoken.sso.model.SaCheckTicketResult;
|
import cn.dev33.satoken.sso.model.SaCheckTicketResult;
|
||||||
|
import cn.dev33.satoken.sso.model.TicketModel;
|
||||||
import cn.dev33.satoken.sso.name.ApiName;
|
import cn.dev33.satoken.sso.name.ApiName;
|
||||||
import cn.dev33.satoken.sso.name.ParamName;
|
import cn.dev33.satoken.sso.name.ParamName;
|
||||||
import cn.dev33.satoken.sso.template.SaSsoClientTemplate;
|
import cn.dev33.satoken.sso.template.SaSsoClientTemplate;
|
||||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
@ -139,7 +142,10 @@ public class SaSsoClientProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3、登录并重定向至back地址
|
// 3、登录并重定向至back地址
|
||||||
stpLogic.login(ctr.loginId, ctr.remainSessionTimeout);
|
stpLogic.login(ctr.loginId, new SaLoginParameter()
|
||||||
|
.setTimeout(ctr.remainTokenTimeout)
|
||||||
|
.setDeviceId(ctr.deviceId)
|
||||||
|
);
|
||||||
return res.redirect(back);
|
return res.redirect(back);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,6 +217,7 @@ public class SaSsoClientProcessor {
|
|||||||
SaRequest req = SaHolder.getRequest();
|
SaRequest req = SaHolder.getRequest();
|
||||||
SaResponse res = SaHolder.getResponse();
|
SaResponse res = SaHolder.getResponse();
|
||||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||||
|
boolean singleDeviceIdLogout = req.isParam(ssoClientTemplate.paramName.singleDeviceIdLogout, "true");
|
||||||
|
|
||||||
// 如果未登录,则无需注销
|
// 如果未登录,则无需注销
|
||||||
if( ! stpLogic.isLogin()) {
|
if( ! stpLogic.isLogin()) {
|
||||||
@ -218,7 +225,11 @@ public class SaSsoClientProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 调用 sso-server 认证中心单点注销API
|
// 调用 sso-server 认证中心单点注销API
|
||||||
SaSsoMessage message = ssoClientTemplate.buildSloMessage(stpLogic.getLoginId());
|
SaLogoutParameter logoutParameter = stpLogic.createSaLogoutParameter();
|
||||||
|
if(singleDeviceIdLogout) {
|
||||||
|
logoutParameter.setDeviceId(stpLogic.getLoginDeviceId());
|
||||||
|
}
|
||||||
|
SaSsoMessage message = ssoClientTemplate.buildSloMessage(stpLogic.getLoginId(), logoutParameter);
|
||||||
SaResult result = ssoClientTemplate.pushMessageAsSaResult(message);
|
SaResult result = ssoClientTemplate.pushMessageAsSaResult(message);
|
||||||
|
|
||||||
// 校验响应状态码
|
// 校验响应状态码
|
||||||
@ -248,18 +259,20 @@ public class SaSsoClientProcessor {
|
|||||||
|
|
||||||
// 获取参数
|
// 获取参数
|
||||||
String loginId = req.getParamNotNull(paramName.loginId);
|
String loginId = req.getParamNotNull(paramName.loginId);
|
||||||
|
String deviceId = req.getParam(paramName.deviceId);
|
||||||
// String client = req.getParam(paramName.client);
|
// String client = req.getParam(paramName.client);
|
||||||
// String autoLogout = req.getParam(paramName.autoLogout);
|
// String autoLogout = req.getParam(paramName.autoLogout);
|
||||||
|
|
||||||
// 校验参数签名
|
// 校验参数签名
|
||||||
if(ssoConfig.getIsCheckSign()) {
|
if(ssoConfig.getIsCheckSign()) {
|
||||||
ssoClientTemplate.getSignTemplate(ssoConfig.getClient()).checkRequest(req, paramName.loginId, paramName.client, paramName.autoLogout);
|
ssoClientTemplate.getSignTemplate(ssoConfig.getClient()).checkRequest(req);
|
||||||
} else {
|
} else {
|
||||||
SaSsoManager.printNoCheckSignWarningByRuntime();
|
SaSsoManager.printNoCheckSignWarningByRuntime();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注销当前应用端会话
|
// 注销当前应用端会话
|
||||||
stpLogic.logout(loginId);
|
SaLogoutParameter logoutParameter = ssoClientTemplate.getStpLogic().createSaLogoutParameter();
|
||||||
|
stpLogic.logout(loginId, logoutParameter.setDeviceId(deviceId));
|
||||||
|
|
||||||
// 响应
|
// 响应
|
||||||
return SaResult.ok("单点注销回调成功");
|
return SaResult.ok("单点注销回调成功");
|
||||||
@ -269,9 +282,10 @@ public class SaSsoClientProcessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 封装:校验ticket,取出loginId,如果 ticket 无效则抛出异常 (适用于模式二或模式三)
|
* 封装:校验ticket,取出loginId,如果 ticket 无效则抛出异常 (适用于模式二或模式三)
|
||||||
|
*
|
||||||
* @param ticket ticket码
|
* @param ticket ticket码
|
||||||
* @param currUri 当前路由的uri,用于计算单点注销回调地址 (如果是使用模式二,可以填写null)
|
* @param currUri 当前路由的uri,用于计算单点注销回调地址 (如果是使用模式二,可以填写null)
|
||||||
* @return loginId
|
* @return SaCheckTicketResult
|
||||||
*/
|
*/
|
||||||
public SaCheckTicketResult checkTicket(String ticket, String currUri) {
|
public SaCheckTicketResult checkTicket(String ticket, String currUri) {
|
||||||
SaSsoClientConfig cfg = ssoClientTemplate.getClientConfig();
|
SaSsoClientConfig cfg = ssoClientTemplate.getClientConfig();
|
||||||
@ -304,18 +318,16 @@ public class SaSsoClientProcessor {
|
|||||||
|
|
||||||
// 校验
|
// 校验
|
||||||
if(result.getCode() != null && result.getCode() == SaResult.CODE_SUCCESS) {
|
if(result.getCode() != null && result.getCode() == SaResult.CODE_SUCCESS) {
|
||||||
// 取出 loginId
|
|
||||||
Object loginId = result.getData();
|
SaCheckTicketResult ctr = new SaCheckTicketResult();
|
||||||
if(SaFoxUtil.isEmpty(loginId)) {
|
ctr.loginId = result.get(paramName.loginId);
|
||||||
throw new SaSsoException("无效ticket:" + ticket).setCode(SaSsoErrorCode.CODE_30004);
|
ctr.tokenValue = result.get(paramName.tokenValue, String.class);
|
||||||
}
|
ctr.deviceId = result.get(paramName.deviceId, String.class);
|
||||||
// 取出 Session 剩余有效期
|
ctr.remainTokenTimeout = result.get(paramName.remainTokenTimeout, Long.class);
|
||||||
Long remainSessionTimeout = result.get(paramName.remainSessionTimeout, Long.class);
|
ctr.remainSessionTimeout = result.get(paramName.remainSessionTimeout, Long.class);
|
||||||
if(remainSessionTimeout == null) {
|
ctr.result = result;
|
||||||
remainSessionTimeout = ssoClientTemplate.getStpLogic().getConfigOrGlobal().getTimeout();
|
|
||||||
}
|
return ctr;
|
||||||
// 构建返回
|
|
||||||
return new SaCheckTicketResult(loginId, remainSessionTimeout, result);
|
|
||||||
} else {
|
} else {
|
||||||
// 将 sso-server 回应的消息作为异常抛出
|
// 将 sso-server 回应的消息作为异常抛出
|
||||||
throw new SaSsoException(result.getMsg()).setCode(SaSsoErrorCode.CODE_30005);
|
throw new SaSsoException(result.getMsg()).setCode(SaSsoErrorCode.CODE_30005);
|
||||||
@ -328,15 +340,18 @@ public class SaSsoClientProcessor {
|
|||||||
// 可能会导致调用失败(注意是可能,而非一定),
|
// 可能会导致调用失败(注意是可能,而非一定),
|
||||||
// 解决方案为:在当前 sso-client 端也按照 sso-server 端的格式重写 SaSsoClientProcessor 里的方法
|
// 解决方案为:在当前 sso-client 端也按照 sso-server 端的格式重写 SaSsoClientProcessor 里的方法
|
||||||
|
|
||||||
// 取出 loginId
|
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||||
Object loginId = SaSsoServerProcessor.instance.ssoServerTemplate.checkTicket(ticket, cfg.getClient());
|
TicketModel ticketModel = SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(ticket, cfg.getClient());
|
||||||
if(SaFoxUtil.isEmpty(loginId)) {
|
|
||||||
throw new SaSsoException("无效ticket:" + ticket).setCode(SaSsoErrorCode.CODE_30004);
|
SaCheckTicketResult ctr = new SaCheckTicketResult();
|
||||||
}
|
ctr.loginId = ticketModel.getLoginId();
|
||||||
// 取出 Session 剩余有效期
|
ctr.tokenValue = ticketModel.getTokenValue();
|
||||||
long remainSessionTimeout = ssoClientTemplate.getStpLogic().getSessionTimeoutByLoginId(loginId);
|
ctr.deviceId = stpLogic.getLoginDeviceIdByToken(ticketModel.getTokenValue());
|
||||||
// 构建返回
|
ctr.remainTokenTimeout = stpLogic.getTokenTimeout(ticketModel.getTokenValue());
|
||||||
return new SaCheckTicketResult(loginId, remainSessionTimeout, null);
|
ctr.remainSessionTimeout = stpLogic.getSessionTimeoutByLoginId(ticketModel.getLoginId());
|
||||||
|
ctr.result = null;
|
||||||
|
|
||||||
|
return ctr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import cn.dev33.satoken.sso.name.ParamName;
|
|||||||
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
||||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ public class SaSsoServerProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 构建并跳转
|
// 构建并跳转
|
||||||
String redirectUrl = ssoServerTemplate.buildRedirectUrl(stpLogic.getLoginId(), client, redirect);
|
String redirectUrl = ssoServerTemplate.buildRedirectUrl(client, redirect, stpLogic.getLoginId(), stpLogic.getTokenValue());
|
||||||
// 构建成功,说明 redirect 地址合法,此时需要更新一下该账号的Session有效期
|
// 构建成功,说明 redirect 地址合法,此时需要更新一下该账号的Session有效期
|
||||||
if(cfg.getAutoRenewTimeout()) {
|
if(cfg.getAutoRenewTimeout()) {
|
||||||
stpLogic.renewTimeout(stpLogic.getConfigOrGlobal().getTimeout());
|
stpLogic.renewTimeout(stpLogic.getConfigOrGlobal().getTimeout());
|
||||||
@ -174,10 +175,15 @@ public class SaSsoServerProcessor {
|
|||||||
SaRequest req = SaHolder.getRequest();
|
SaRequest req = SaHolder.getRequest();
|
||||||
SaResponse res = SaHolder.getResponse();
|
SaResponse res = SaHolder.getResponse();
|
||||||
Object loginId = ssoServerTemplate.getStpLogic().getLoginIdDefaultNull();
|
Object loginId = ssoServerTemplate.getStpLogic().getLoginIdDefaultNull();
|
||||||
|
boolean singleDeviceIdLogout = req.isParam(ssoServerTemplate.paramName.singleDeviceIdLogout, "true");
|
||||||
|
|
||||||
// 单点注销
|
// 单点注销
|
||||||
if(SaFoxUtil.isNotEmpty(loginId)) {
|
if(SaFoxUtil.isNotEmpty(loginId)) {
|
||||||
ssoServerTemplate.ssoLogout(loginId);
|
SaLogoutParameter logoutParameter = ssoServerTemplate.getStpLogic().createSaLogoutParameter();
|
||||||
|
if(singleDeviceIdLogout) {
|
||||||
|
logoutParameter.setDeviceId(ssoServerTemplate.getStpLogic().getLoginDeviceId());
|
||||||
|
}
|
||||||
|
ssoServerTemplate.ssoLogout(loginId, logoutParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 完成
|
// 完成
|
||||||
|
@ -25,6 +25,7 @@ import cn.dev33.satoken.sso.exception.SaSsoException;
|
|||||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||||
import cn.dev33.satoken.sso.message.handle.client.SaSsoMessageLogoutCallHandle;
|
import cn.dev33.satoken.sso.message.handle.client.SaSsoMessageLogoutCallHandle;
|
||||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
@ -160,15 +161,18 @@ public class SaSsoClientTemplate extends SaSsoTemplate {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建消息:单点注销
|
* 构建消息:单点注销
|
||||||
|
*
|
||||||
* @param loginId 要注销的账号 id
|
* @param loginId 要注销的账号 id
|
||||||
|
* @param logoutParameter 单点注销
|
||||||
* @return 单点注销URL
|
* @return 单点注销URL
|
||||||
*/
|
*/
|
||||||
public SaSsoMessage buildSloMessage(Object loginId) {
|
public SaSsoMessage buildSloMessage(Object loginId, SaLogoutParameter logoutParameter) {
|
||||||
SaSsoClientConfig ssoConfig = getClientConfig();
|
SaSsoClientConfig ssoConfig = getClientConfig();
|
||||||
SaSsoMessage message = new SaSsoMessage();
|
SaSsoMessage message = new SaSsoMessage();
|
||||||
message.setType(SaSsoConsts.MESSAGE_SIGNOUT);
|
message.setType(SaSsoConsts.MESSAGE_SIGNOUT);
|
||||||
message.set(paramName.client, ssoConfig.getClient());
|
message.set(paramName.client, ssoConfig.getClient());
|
||||||
message.set(paramName.loginId, loginId);
|
message.set(paramName.loginId, loginId);
|
||||||
|
message.set(paramName.deviceId, logoutParameter.getDeviceId());
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import cn.dev33.satoken.sso.message.handle.server.SaSsoMessageSignoutHandle;
|
|||||||
import cn.dev33.satoken.sso.model.SaSsoClientInfo;
|
import cn.dev33.satoken.sso.model.SaSsoClientInfo;
|
||||||
import cn.dev33.satoken.sso.model.TicketModel;
|
import cn.dev33.satoken.sso.model.TicketModel;
|
||||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||||
|
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||||
import cn.dev33.satoken.strategy.SaStrategy;
|
import cn.dev33.satoken.strategy.SaStrategy;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
@ -67,7 +68,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
* @param ticket ticket码
|
* @param ticket ticket码
|
||||||
* @param loginId 账号id
|
* @param loginId 账号id
|
||||||
*/
|
*/
|
||||||
public void saveTicketIndex(String client, String ticket, Object loginId) {
|
public void saveTicketIndex(String client, Object loginId, String ticket) {
|
||||||
long ticketTimeout = getServerConfig().getTicketTimeout();
|
long ticketTimeout = getServerConfig().getTicketTimeout();
|
||||||
SaManager.getSaTokenDao().set(splicingTicketIndexKey(client, loginId), String.valueOf(ticket), ticketTimeout);
|
SaManager.getSaTokenDao().set(splicingTicketIndexKey(client, loginId), String.valueOf(ticket), ticketTimeout);
|
||||||
}
|
}
|
||||||
@ -186,56 +187,65 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
|
|
||||||
//
|
//
|
||||||
/**
|
/**
|
||||||
* 根据 账号id 创建一个 Ticket码
|
* 根据参数创建一个 ticket 码
|
||||||
* @param loginId 账号id
|
*
|
||||||
* @param client 客户端标识
|
* @param client 客户端标识
|
||||||
|
* @param loginId 账号 id
|
||||||
|
* @param tokenValue 会话 Token
|
||||||
* @return Ticket码
|
* @return Ticket码
|
||||||
*/
|
*/
|
||||||
public String createTicket(Object loginId, String client) {
|
public String createTicket(String client, Object loginId, String tokenValue) {
|
||||||
// 创建 Ticket
|
// 创建 Ticket
|
||||||
String ticket = randomTicket(loginId);
|
String ticket = randomTicket(loginId);
|
||||||
TicketModel ticketModel = new TicketModel();
|
TicketModel ticketModel = new TicketModel();
|
||||||
ticketModel.setTicket(ticket);
|
ticketModel.setTicket(ticket);
|
||||||
ticketModel.setClient(client);
|
ticketModel.setClient(client);
|
||||||
ticketModel.setLoginId(loginId);
|
ticketModel.setLoginId(loginId);
|
||||||
// TODO ticketModel.setDeviceId();
|
ticketModel.setTokenValue(tokenValue);
|
||||||
|
|
||||||
// 保存 Ticket
|
// 保存 Ticket
|
||||||
saveTicket(ticketModel);
|
saveTicket(ticketModel);
|
||||||
saveTicketIndex(client, ticket, loginId);
|
saveTicketIndex(client, loginId, ticket);
|
||||||
|
|
||||||
// 返回 Ticket
|
// 返回 Ticket
|
||||||
return ticket;
|
return ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验 Ticket 码,获取账号id,如果此ticket是有效的,则立即删除
|
* 校验 Ticket,无效 ticket 会抛出异常
|
||||||
|
*
|
||||||
* @param ticket Ticket码
|
* @param ticket Ticket码
|
||||||
* @return 账号id
|
* @return /
|
||||||
*/
|
*/
|
||||||
public Object checkTicket(String ticket) {
|
public TicketModel checkTicket(String ticket) {
|
||||||
return checkTicket(ticket, SaSsoConsts.CLIENT_WILDCARD);
|
TicketModel ticketModel = getTicket(ticket);
|
||||||
|
if(ticketModel == null) {
|
||||||
|
throw new SaSsoException("无效 ticket : " + ticket).setCode(SaSsoErrorCode.CODE_30004);
|
||||||
|
}
|
||||||
|
return ticketModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验 Ticket 码,获取账号id,如果此ticket是有效的,则立即删除
|
* 校验 Ticket 码,无效 ticket 会抛出异常,如果此ticket是有效的,则立即删除
|
||||||
* @param ticket Ticket码
|
* @param ticket Ticket码
|
||||||
* @param client client 标识
|
|
||||||
* @return 账号id
|
* @return 账号id
|
||||||
*/
|
*/
|
||||||
public Object checkTicket(String ticket, String client) {
|
public TicketModel checkTicketParamAndDelete(String ticket) {
|
||||||
// 读取 loginId
|
return checkTicketParamAndDelete(ticket, SaSsoConsts.CLIENT_WILDCARD);
|
||||||
TicketModel ticketModel = getTicket(ticket);
|
|
||||||
if(ticketModel == null) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object loginId = ticketModel.getLoginId();
|
/**
|
||||||
String ticketClient = ticketModel.getClient();
|
* 校验 Ticket,无效 ticket 会抛出异常,如果此ticket是有效的,则立即删除
|
||||||
|
*
|
||||||
// 解析出这个 ticket 关联的 Client
|
* @param ticket Ticket码
|
||||||
|
* @param client client 标识
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public TicketModel checkTicketParamAndDelete(String ticket, String client) {
|
||||||
|
TicketModel ticketModel = checkTicket(ticket);
|
||||||
|
|
||||||
// 校验 client 参数是否正确,即:创建 ticket 的 client 和当前校验 ticket 的 client 是否一致
|
// 校验 client 参数是否正确,即:创建 ticket 的 client 和当前校验 ticket 的 client 是否一致
|
||||||
|
String ticketClient = ticketModel.getClient();
|
||||||
if(SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
if(SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
||||||
// 如果提供的是通配符,直接越过 client 校验
|
// 如果提供的是通配符,直接越过 client 校验
|
||||||
} else if (SaFoxUtil.isEmpty(client) && SaFoxUtil.isEmpty(ticketClient)) {
|
} else if (SaFoxUtil.isEmpty(client) && SaFoxUtil.isEmpty(ticketClient)) {
|
||||||
@ -249,10 +259,10 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
|
|
||||||
// 删除 ticket 信息,使其只有一次性有效
|
// 删除 ticket 信息,使其只有一次性有效
|
||||||
deleteTicket(ticket);
|
deleteTicket(ticket);
|
||||||
deleteTicketIndex(ticket, loginId);
|
deleteTicketIndex(client, ticketModel.getLoginId());
|
||||||
|
|
||||||
//
|
//
|
||||||
return loginId;
|
return ticketModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -346,13 +356,15 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
// ------------------- 重定向 URL 构建与校验 -------------------
|
// ------------------- 重定向 URL 构建与校验 -------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建URL:Server端向Client下放ticket的地址
|
* 构建 URL:sso-server 端向 sso-client 下放 ticket 的地址
|
||||||
* @param loginId 账号id
|
*
|
||||||
* @param client 客户端标识
|
* @param client 客户端标识
|
||||||
* @param redirect Client端提供的重定向地址
|
* @param redirect sso-client 端的重定向地址
|
||||||
* @return see note
|
* @param loginId 账号 id
|
||||||
|
* @param tokenValue 会话 token
|
||||||
|
* @return /
|
||||||
*/
|
*/
|
||||||
public String buildRedirectUrl(Object loginId, String client, String redirect) {
|
public String buildRedirectUrl(String client, String redirect, Object loginId, String tokenValue) {
|
||||||
|
|
||||||
// 校验 重定向地址 是否合法
|
// 校验 重定向地址 是否合法
|
||||||
checkRedirectUrl(client, redirect);
|
checkRedirectUrl(client, redirect);
|
||||||
@ -361,7 +373,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
deleteTicket(getTicketValue(client, loginId));
|
deleteTicket(getTicketValue(client, loginId));
|
||||||
|
|
||||||
// 创建 新Ticket
|
// 创建 新Ticket
|
||||||
String ticket = createTicket(loginId, client);
|
String ticket = createTicket(client, loginId, tokenValue);
|
||||||
|
|
||||||
// 构建 授权重定向地址 (Server端 根据此地址向 Client端 下放Ticket)
|
// 构建 授权重定向地址 (Server端 根据此地址向 Client端 下放Ticket)
|
||||||
return SaFoxUtil.joinParam(encodeBackParam(redirect), paramName.ticket, ticket);
|
return SaFoxUtil.joinParam(encodeBackParam(redirect), paramName.ticket, ticket);
|
||||||
@ -521,7 +533,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
if(scmList.size() > maxRegClient) {
|
if(scmList.size() > maxRegClient) {
|
||||||
SaSsoClientInfo removeScm = scmList.remove(0);
|
SaSsoClientInfo removeScm = scmList.remove(0);
|
||||||
notifyClientLogout(loginId, removeScm, true);
|
notifyClientLogout(loginId, null, removeScm, true);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -557,12 +569,24 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定账号单点注销
|
* 指定账号单点注销
|
||||||
|
*
|
||||||
* @param loginId 指定账号
|
* @param loginId 指定账号
|
||||||
*/
|
*/
|
||||||
public void ssoLogout(Object loginId) {
|
public void ssoLogout(Object loginId) {
|
||||||
|
ssoLogout(loginId, getStpLogic().createSaLogoutParameter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定账号单点注销
|
||||||
|
*
|
||||||
|
* @param loginId 指定账号
|
||||||
|
* @param logoutParameter 注销参数
|
||||||
|
*/
|
||||||
|
public void ssoLogout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||||
|
|
||||||
// 1、消息推送:单点注销
|
// 1、消息推送:单点注销
|
||||||
pushToAllClientByLogoutCall(loginId);
|
// TODO 需要把对应的 SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_ 记录也删掉
|
||||||
|
pushToAllClientByLogoutCall(loginId, logoutParameter);
|
||||||
|
|
||||||
// 2、SaSession 挂载的 Client 端注销会话
|
// 2、SaSession 挂载的 Client 端注销会话
|
||||||
SaSession session = getStpLogic().getSessionByLoginId(loginId, false);
|
SaSession session = getStpLogic().getSessionByLoginId(loginId, false);
|
||||||
@ -571,20 +595,21 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
}
|
}
|
||||||
List<SaSsoClientInfo> scmList = session.get(SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_, ArrayList::new);
|
List<SaSsoClientInfo> scmList = session.get(SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_, ArrayList::new);
|
||||||
scmList.forEach(scm -> {
|
scmList.forEach(scm -> {
|
||||||
notifyClientLogout(loginId, scm, false);
|
notifyClientLogout(loginId, logoutParameter.getDeviceId(), scm, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3、Server 端本身注销
|
// 3、Server 端本身注销
|
||||||
getStpLogic().logout(loginId);
|
getStpLogic().logout(loginId, logoutParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知指定账号的指定客户端注销
|
* 通知指定账号的指定客户端注销
|
||||||
* @param loginId 指定账号
|
* @param loginId 指定账号
|
||||||
|
* @param deviceId 指定设备 id
|
||||||
* @param scm 客户端信息对象
|
* @param scm 客户端信息对象
|
||||||
* @param autoLogout 是否为超过 maxRegClient 的自动注销
|
* @param autoLogout 是否为超过 maxRegClient 的自动注销
|
||||||
*/
|
*/
|
||||||
public void notifyClientLogout(Object loginId, SaSsoClientInfo scm, boolean autoLogout) {
|
public void notifyClientLogout(Object loginId, String deviceId, SaSsoClientInfo scm, boolean autoLogout) {
|
||||||
|
|
||||||
// 如果给个null值,不进行任何操作
|
// 如果给个null值,不进行任何操作
|
||||||
if(scm == null || scm.mode != SaSsoConsts.SSO_MODE_3) {
|
if(scm == null || scm.mode != SaSsoConsts.SSO_MODE_3) {
|
||||||
@ -601,6 +626,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
Map<String, Object> paramsMap = new TreeMap<>();
|
Map<String, Object> paramsMap = new TreeMap<>();
|
||||||
paramsMap.put(paramName.client, scm.getClient());
|
paramsMap.put(paramName.client, scm.getClient());
|
||||||
paramsMap.put(paramName.loginId, loginId);
|
paramsMap.put(paramName.loginId, loginId);
|
||||||
|
paramsMap.put(paramName.deviceId, deviceId);
|
||||||
paramsMap.put(paramName.autoLogout, autoLogout);
|
paramsMap.put(paramName.autoLogout, autoLogout);
|
||||||
String signParamsStr = getSignTemplate(scm.getClient()).addSignParamsAndJoin(paramsMap);
|
String signParamsStr = getSignTemplate(scm.getClient()).addSignParamsAndJoin(paramsMap);
|
||||||
|
|
||||||
@ -680,14 +706,16 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
|||||||
* 向所有 Client 推送消息:单点注销回调
|
* 向所有 Client 推送消息:单点注销回调
|
||||||
*
|
*
|
||||||
* @param loginId /
|
* @param loginId /
|
||||||
|
* @param logoutParameter 注销参数
|
||||||
*/
|
*/
|
||||||
public void pushToAllClientByLogoutCall(Object loginId) {
|
public void pushToAllClientByLogoutCall(Object loginId, SaLogoutParameter logoutParameter) {
|
||||||
List<SaSsoClientModel> npClients = getNeedPushClients();
|
List<SaSsoClientModel> npClients = getNeedPushClients();
|
||||||
for (SaSsoClientModel client : npClients) {
|
for (SaSsoClientModel client : npClients) {
|
||||||
if(client.getIsSlo()) {
|
if(client.getIsSlo()) {
|
||||||
SaSsoMessage message = new SaSsoMessage();
|
SaSsoMessage message = new SaSsoMessage();
|
||||||
message.setType(SaSsoConsts.MESSAGE_LOGOUT_CALL);
|
message.setType(SaSsoConsts.MESSAGE_LOGOUT_CALL);
|
||||||
message.set(paramName.loginId, loginId);
|
message.set(paramName.loginId, loginId);
|
||||||
|
message.set(paramName.deviceId, logoutParameter.getDeviceId());
|
||||||
pushMessage(client, message);
|
pushMessage(client, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.sso.template;
|
package cn.dev33.satoken.sso.template;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.sso.model.TicketModel;
|
||||||
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
|
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
|
||||||
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
|
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
|
||||||
|
|
||||||
@ -31,13 +32,15 @@ public class SaSsoUtil {
|
|||||||
// ---------------------- Ticket 操作 ----------------------
|
// ---------------------- Ticket 操作 ----------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 账号id 创建一个 Ticket码
|
* 根据参数创建一个 ticket 码
|
||||||
* @param loginId 账号id
|
*
|
||||||
* @param client 客户端标识
|
* @param client 客户端标识
|
||||||
|
* @param loginId 账号 id
|
||||||
|
* @param deviceId 设备 id
|
||||||
* @return Ticket码
|
* @return Ticket码
|
||||||
*/
|
*/
|
||||||
public static String createTicket(Object loginId, String client) {
|
public static String createTicket(String client, Object loginId, String deviceId) {
|
||||||
return SaSsoServerProcessor.instance.ssoServerTemplate.createTicket(loginId, client);
|
return SaSsoServerProcessor.instance.ssoServerTemplate.createTicket(client, loginId, deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,22 +81,22 @@ public class SaSsoUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验 Ticket 码,获取账号id,如果此ticket是有效的,则立即删除
|
* 校验 Ticket,无效 ticket 会抛出异常,如果此ticket是有效的,则立即删除
|
||||||
* @param ticket Ticket码
|
* @param ticket Ticket码
|
||||||
* @return 账号id
|
* @return 账号id
|
||||||
*/
|
*/
|
||||||
public static Object checkTicket(String ticket) {
|
public static TicketModel checkTicket(String ticket) {
|
||||||
return SaSsoServerProcessor.instance.ssoServerTemplate.checkTicket(ticket);
|
return SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验ticket码,获取账号id,如果此ticket是有效的,则立即删除
|
* 校验ticket码,无效 ticket 会抛出异常,如果此ticket是有效的,则立即删除
|
||||||
* @param ticket Ticket码
|
* @param ticket Ticket码
|
||||||
* @param client client 标识
|
* @param client client 标识
|
||||||
* @return 账号id
|
* @return 账号id
|
||||||
*/
|
*/
|
||||||
public static Object checkTicket(String ticket, String client) {
|
public static TicketModel checkTicket(String ticket, String client) {
|
||||||
return SaSsoServerProcessor.instance.ssoServerTemplate.checkTicket(ticket, client);
|
return SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(ticket, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,14 +163,16 @@ public class SaSsoUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建URL:Server端向Client下放ticket的地址
|
* 构建 URL:sso-server 端向 sso-client 下放 ticket 的地址
|
||||||
* @param loginId 账号id
|
*
|
||||||
* @param client 客户端标识
|
* @param client 客户端标识
|
||||||
* @param redirect Client端提供的重定向地址
|
* @param redirect sso-client 端的重定向地址
|
||||||
* @return see note
|
* @param loginId 账号 id
|
||||||
|
* @param tokenValue 会话 token
|
||||||
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static String buildRedirectUrl(Object loginId, String client, String redirect) {
|
public static String buildRedirectUrl(String client, String redirect, Object loginId, String tokenValue) {
|
||||||
return SaSsoServerProcessor.instance.ssoServerTemplate.buildRedirectUrl(loginId, client, redirect);
|
return SaSsoServerProcessor.instance.ssoServerTemplate.buildRedirectUrl(client, redirect, loginId, tokenValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user