mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-09-22 20:13:34 +08:00
更换单点注销接口响应格式
This commit is contained in:
@@ -279,12 +279,16 @@ public class SaSsoConfig implements Serializable {
|
||||
/**
|
||||
* SSO-Server端:未登录时返回的View
|
||||
*/
|
||||
public Supplier<Object> notLoginView = () -> "当前会话在SSO-Server认证中心尚未登录";
|
||||
public Supplier<Object> notLoginView = () -> {
|
||||
return "当前会话在SSO-Server认证中心尚未登录";
|
||||
};
|
||||
|
||||
/**
|
||||
* SSO-Server端:登录函数
|
||||
*/
|
||||
public BiFunction<String, String, Object> doLoginHandle = (name, pwd) -> SaResult.error();
|
||||
public BiFunction<String, String, Object> doLoginHandle = (name, pwd) -> {
|
||||
return SaResult.error();
|
||||
};
|
||||
|
||||
/**
|
||||
* SSO-Client端:自定义校验Ticket返回值的处理逻辑 (每次从认证中心获取校验Ticket的结果后调用)
|
||||
@@ -294,7 +298,9 @@ public class SaSsoConfig implements Serializable {
|
||||
/**
|
||||
* SSO-Client端:发送Http请求的处理函数
|
||||
*/
|
||||
public Function<String, Object> sendHttp = url -> {throw new SaTokenException("请配置Http处理器");};
|
||||
public Function<String, String> sendHttp = url -> {
|
||||
throw new SaTokenException("请配置 Http 请求处理器");
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -349,7 +355,7 @@ public class SaSsoConfig implements Serializable {
|
||||
* @param sendHttp SSO-Client端:发送Http请求的处理函数
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoConfig setSendHttp(Function<String, Object> sendHttp) {
|
||||
public SaSsoConfig setSendHttp(Function<String, String> sendHttp) {
|
||||
this.sendHttp = sendHttp;
|
||||
return this;
|
||||
}
|
||||
@@ -357,7 +363,7 @@ public class SaSsoConfig implements Serializable {
|
||||
/**
|
||||
* @return 函数 SSO-Client端:发送Http请求的处理函数
|
||||
*/
|
||||
public Function<String, Object> getSendHttp() {
|
||||
public Function<String, String> getSendHttp() {
|
||||
return sendHttp;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,8 @@
|
||||
package cn.dev33.satoken.sso;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.config.SaSsoConfig;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.context.model.SaRequest;
|
||||
@@ -19,6 +22,8 @@ import cn.dev33.satoken.util.SaResult;
|
||||
*/
|
||||
public class SaSsoHandle {
|
||||
|
||||
// ----------- SSO-Server 端路由分发
|
||||
|
||||
/**
|
||||
* 处理Server端所有请求
|
||||
* @return 处理结果
|
||||
@@ -46,14 +51,14 @@ public class SaSsoHandle {
|
||||
return ssoCheckTicket();
|
||||
}
|
||||
|
||||
// SSO-Server端:单点注销 [模式一] (不带loginId参数)
|
||||
// SSO-Server端:单点注销 [用户访问式] (不带loginId参数)
|
||||
if(req.isPath(Api.ssoLogout) && cfg.getIsSlo() && req.hasParam(ParamName.loginId) == false) {
|
||||
return ssoServerLogoutType1();
|
||||
return ssoLogoutByUserVisit();
|
||||
}
|
||||
|
||||
// SSO-Server端:单点注销 [模式三] (带loginId参数)
|
||||
// SSO-Server端:单点注销 [Client调用式] (带loginId参数 & isHttp=true)
|
||||
if(req.isPath(Api.ssoLogout) && cfg.getIsHttp() && cfg.getIsSlo() && req.hasParam(ParamName.loginId)) {
|
||||
return ssoServerLogout();
|
||||
return ssoLogoutByClientHttp();
|
||||
}
|
||||
|
||||
// 默认返回
|
||||
@@ -116,38 +121,47 @@ public class SaSsoHandle {
|
||||
String ticket = req.getParam(ParamName.ticket);
|
||||
String sloCallback = req.getParam(ParamName.ssoLogoutCall);
|
||||
|
||||
// 校验ticket,获取对应的账号id
|
||||
// 校验ticket,获取 loginId
|
||||
Object loginId = SaSsoUtil.checkTicket(ticket);
|
||||
|
||||
|
||||
// 注册此客户端的单点注销回调URL
|
||||
SaSsoUtil.registerSloCallbackUrl(loginId, sloCallback);
|
||||
|
||||
// 返回给Client端
|
||||
return loginId;
|
||||
// 给 client 端响应结果
|
||||
if(SaFoxUtil.isEmpty(loginId)) {
|
||||
return SaResult.error("无效ticket:" + ticket);
|
||||
} else {
|
||||
return SaResult.data(loginId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO-Server端:单点注销 [模式一]
|
||||
* SSO-Server端:单点注销 [用户访问式]
|
||||
* @return 处理结果
|
||||
*/
|
||||
public static Object ssoServerLogoutType1() {
|
||||
public static Object ssoLogoutByUserVisit() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
SaSsoConfig cfg = SaSsoManager.getConfig();
|
||||
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
|
||||
String loginId = req.getParam(ParamName.loginId);
|
||||
|
||||
// step.1 遍历 Client 端注销
|
||||
SaSsoUtil.forEachSloUrl(loginId, url -> cfg.getSendHttp().apply(url));
|
||||
|
||||
// 开始处理
|
||||
// step.2 Server 端注销
|
||||
stpLogic.logout();
|
||||
|
||||
// 返回
|
||||
// 完成
|
||||
return ssoLogoutBack(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO-Server端:单点注销 [模式三]
|
||||
* SSO-Server端:单点注销 [Client调用式]
|
||||
* @return 处理结果
|
||||
*/
|
||||
public static Object ssoServerLogout() {
|
||||
public static Object ssoLogoutByClientHttp() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaSsoConfig cfg = SaSsoManager.getConfig();
|
||||
@@ -157,21 +171,22 @@ public class SaSsoHandle {
|
||||
String loginId = req.getParam(ParamName.loginId);
|
||||
String secretkey = req.getParam(ParamName.secretkey);
|
||||
|
||||
// 遍历通知Client端注销会话
|
||||
// step.1 校验秘钥
|
||||
SaSsoUtil.checkSecretkey(secretkey);
|
||||
|
||||
// step.2 遍历通知Client端注销会话
|
||||
// step.2 遍历 Client 端注销
|
||||
SaSsoUtil.forEachSloUrl(loginId, url -> cfg.getSendHttp().apply(url));
|
||||
|
||||
// step.3 Server端注销
|
||||
// step.3 Server 端注销
|
||||
stpLogic.logout(loginId);
|
||||
|
||||
// 完成
|
||||
return SaSsoConsts.OK;
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
|
||||
// ----------- SSO-Client 端路由分发
|
||||
|
||||
/**
|
||||
* 处理Client端所有请求
|
||||
* @return 处理结果
|
||||
@@ -236,20 +251,21 @@ public class SaSsoHandle {
|
||||
String serverAuthUrl = SaSsoUtil.buildServerAuthUrl(SaHolder.getRequest().getUrl(), back);
|
||||
return res.redirect(serverAuthUrl);
|
||||
} else {
|
||||
// ------- 1、校验ticket,获取账号id
|
||||
// ------- 1、校验ticket,获取 loginId
|
||||
Object loginId = checkTicket(ticket, Api.ssoLogin);
|
||||
|
||||
// Be: 如果开发者自定义了处理逻辑
|
||||
if(cfg.getTicketResultHandle() != null) {
|
||||
return cfg.getTicketResultHandle().apply(loginId, back);
|
||||
}
|
||||
// ------- 2、如果loginId有值,说明ticket有效,进行登录并重定向至back地址
|
||||
if(loginId != null ) {
|
||||
|
||||
// ------- 2、如果 loginId 无值,说明 ticket 无效
|
||||
if(SaFoxUtil.isEmpty(loginId)) {
|
||||
throw new SaSsoException("无效ticket:" + ticket).setCode(SaSsoExceptionCode.CODE_20004);
|
||||
} else {
|
||||
// 3、如果 loginId 有值,说明 ticket 有效,此时进行登录并重定向至back地址
|
||||
stpLogic.login(loginId);
|
||||
return res.redirect(back);
|
||||
} else {
|
||||
// 如果ticket无效:
|
||||
throw new SaSsoException("无效ticket:" + ticket).setCode(SaSsoExceptionCode.CODE_20004);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,7 +295,6 @@ public class SaSsoHandle {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
SaSsoConfig cfg = SaSsoManager.getConfig();
|
||||
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
|
||||
|
||||
// 如果未登录,则无需注销
|
||||
@@ -289,17 +304,19 @@ public class SaSsoHandle {
|
||||
|
||||
// 调用SSO-Server认证中心API,进行注销
|
||||
String url = SaSsoUtil.buildSloUrl(stpLogic.getLoginId());
|
||||
String body = String.valueOf(cfg.getSendHttp().apply(url));
|
||||
if(SaSsoConsts.OK.equals(body) == false) {
|
||||
return SaResult.error("单点注销失败");
|
||||
}
|
||||
SaResult result = request(url);
|
||||
|
||||
// 返回
|
||||
return ssoLogoutBack(req, res);
|
||||
// 校验
|
||||
if(result.getCode() == SaResult.CODE_SUCCESS) {
|
||||
return ssoLogoutBack(req, res);
|
||||
} else {
|
||||
// 将 sso-server 回应的消息作为异常抛出
|
||||
throw new SaSsoException(result.getMsg()).setCode(SaSsoExceptionCode.CODE_20006);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO-Client端:单点注销的回调 [模式三]
|
||||
* SSO-Client端:单点注销的回调 [模式三]
|
||||
* @return 处理结果
|
||||
*/
|
||||
public static Object ssoLogoutCall() {
|
||||
@@ -311,11 +328,17 @@ public class SaSsoHandle {
|
||||
String loginId = req.getParam(ParamName.loginId);
|
||||
String secretkey = req.getParam(ParamName.secretkey);
|
||||
|
||||
// 注销当前应用端会话
|
||||
SaSsoUtil.checkSecretkey(secretkey);
|
||||
stpLogic.logout(loginId);
|
||||
return SaSsoConsts.OK;
|
||||
|
||||
// 响应
|
||||
return SaResult.ok("单点注销回调成功");
|
||||
}
|
||||
|
||||
|
||||
// ----------- 工具方法
|
||||
|
||||
/**
|
||||
* 封装:单点注销成功后返回结果
|
||||
* @param req SaRequest对象
|
||||
@@ -348,20 +371,41 @@ public class SaSsoHandle {
|
||||
*/
|
||||
public static Object checkTicket(String ticket, String currUri) {
|
||||
SaSsoConfig cfg = SaSsoManager.getConfig();
|
||||
|
||||
// --------- 两种模式
|
||||
if(cfg.getIsHttp()) {
|
||||
// 模式三:使用http请求校验ticket
|
||||
// 模式三:使用 http 请求从认证中心校验ticket
|
||||
String ssoLogoutCall = null;
|
||||
if(cfg.getIsSlo()) {
|
||||
ssoLogoutCall = SaHolder.getRequest().getUrl().replace(currUri, Api.ssoLogoutCall);
|
||||
}
|
||||
|
||||
// 发起请求
|
||||
String checkUrl = SaSsoUtil.buildCheckTicketUrl(ticket, ssoLogoutCall);
|
||||
Object body = cfg.getSendHttp().apply(checkUrl);
|
||||
return (SaFoxUtil.isEmpty(body) ? null : body);
|
||||
SaResult result = request(checkUrl);
|
||||
|
||||
// 校验
|
||||
if(result.getCode() == SaResult.CODE_SUCCESS) {
|
||||
return result.getData();
|
||||
} else {
|
||||
// 将 sso-server 回应的消息作为异常抛出
|
||||
throw new SaSsoException(result.getMsg()).setCode(SaSsoExceptionCode.CODE_20005);
|
||||
}
|
||||
} else {
|
||||
// 模式二:直连Redis校验ticket
|
||||
return SaSsoUtil.checkTicket(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发出请求,并返回 SaResult 结果
|
||||
* @param url 请求地址
|
||||
* @return 返回的结果
|
||||
*/
|
||||
public static SaResult request(String url) {
|
||||
String body = SaSsoManager.getConfig().getSendHttp().apply(url);
|
||||
Map<String, Object> map = SaManager.getSaJsonTemplate().parseJsonToMap(body);
|
||||
return new SaResult(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,11 @@ public class SaSsoExceptionCode {
|
||||
|
||||
/** 提供的 ticket 是无效的 */
|
||||
public static final int CODE_20004 = 20004;
|
||||
|
||||
|
||||
|
||||
/** 在模式三下,sso-client 调用 sso-server 端 校验ticket接口 时,得到的响应是校验失败 */
|
||||
public static final int CODE_20005 = 20005;
|
||||
|
||||
/** 在模式三下,sso-client 调用 sso-server 端 单点注销接口 时,得到的响应是注销失败 */
|
||||
public static final int CODE_20006 = 20006;
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user