mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-06-28 13:34:18 +08:00
refactor: 重构 sa-token-sso 模块代码及注释,提高代码可读性
This commit is contained in:
parent
b59fa26edf
commit
213d98d848
@ -22,7 +22,7 @@ public class SsoClientController implements Render {
|
||||
@Mapping("/")
|
||||
public String index() {
|
||||
String authUrl = SaSsoManager.getClientConfig().splicingAuthUrl();
|
||||
String solUrl = SaSsoManager.getClientConfig().splicingSloUrl();
|
||||
String solUrl = SaSsoManager.getClientConfig().splicingSignoutUrl();
|
||||
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> " +
|
||||
|
@ -18,7 +18,7 @@ public class SsoClientController {
|
||||
@RequestMapping("/")
|
||||
public String index() {
|
||||
String authUrl = SaSsoManager.getClientConfig().splicingAuthUrl();
|
||||
String solUrl = SaSsoManager.getClientConfig().splicingSloUrl();
|
||||
String solUrl = SaSsoManager.getClientConfig().splicingSignoutUrl();
|
||||
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> " +
|
||||
|
@ -20,7 +20,7 @@ public class SsoClientController {
|
||||
// 首页
|
||||
@RequestMapping("/")
|
||||
public String index() {
|
||||
String solUrl = SaSsoManager.getClientConfig().splicingSloUrl();
|
||||
String solUrl = SaSsoManager.getClientConfig().splicingSignoutUrl();
|
||||
String str = "<h2>Sa-Token SSO-Client 应用端</h2>" +
|
||||
"<p>当前会话是否登录:" + StpUtil.isLogin() + "</p>" +
|
||||
"<p><a href=\"javascript:location.href='/sso/login?back=' + encodeURIComponent(location.href);\">登录</a> " +
|
||||
|
@ -70,18 +70,18 @@ public class SaSsoManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 在启动时检测到 sa-token.sso.is-check-sign=false 时,输出警告信息
|
||||
// 在启动时检测到 sa-token.sso-[server/client].is-check-sign=false 时,输出警告信息
|
||||
public static void printNoCheckSignWarningByStartup() {
|
||||
System.err.println("-----------------------------------------------------------------------------");
|
||||
System.err.println("警告信息:");
|
||||
System.err.println("当前配置项 sa-token.sso.is-check-sign=false 代表跳过 SSO 参数签名校验");
|
||||
System.err.println("当前配置项 sa-token.sso-[server/client].is-check-sign=false 代表跳过 SSO 参数签名校验");
|
||||
System.err.println("此模式仅为方便本地调试使用,生产环境下请务必配置为 true (配置项默认为true)");
|
||||
System.err.println("-----------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
// 在运行时检测到 sa-token.sso.is-check-sign=false 时,输出警告信息
|
||||
// 在运行时检测到 sa-token.sso-[server/client].is-check-sign=false 时,输出警告信息
|
||||
public static void printNoCheckSignWarningByRuntime() {
|
||||
System.err.println("警告信息:当前配置项 sa-token.sso.is-check-sign=false 已跳过参数签名校验," +
|
||||
System.err.println("警告信息:当前配置项 sa-token.sso-[server/client].is-check-sign=false 已跳过参数签名校验," +
|
||||
"此模式仅为方便本地调试使用,生产环境下请务必配置为 true (配置项默认为true)");
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 单点登录模块 配置类 (Client端)
|
||||
* Sa-Token SSO Client 端 配置类
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.30.0
|
||||
@ -36,35 +36,35 @@ public class SaSsoClientConfig implements Serializable {
|
||||
public String mode = "";
|
||||
|
||||
/**
|
||||
* 当前 Client 标识
|
||||
* 当前 Client 标识(非必填,不填时代表当前应用是一个匿名应用)
|
||||
*/
|
||||
public String client;
|
||||
|
||||
/**
|
||||
* 配置 Server 端主机总地址
|
||||
* 配置 SSO Server 端主机总地址
|
||||
*/
|
||||
public String serverUrl;
|
||||
|
||||
/**
|
||||
* 单独配置 Server 端单点登录授权地址
|
||||
* 单独配置 Server 端:单点登录授权地址
|
||||
*/
|
||||
public String authUrl = "/sso/auth";
|
||||
|
||||
/**
|
||||
* 单独配置 Server 端查询数据 getData 地址
|
||||
* 单独配置 Server 端:单点注销地址
|
||||
*/
|
||||
public String getDataUrl = "/sso/getData";
|
||||
public String signoutUrl = "/sso/signout";
|
||||
|
||||
/**
|
||||
* 单独配置 Server 端单点注销地址
|
||||
*/
|
||||
public String sloUrl = "/sso/signout";
|
||||
|
||||
/**
|
||||
* 单独配置 Server 端推送消息地址
|
||||
* 单独配置 Server 端:推送消息地址
|
||||
*/
|
||||
public String pushUrl = "/sso/pushS";
|
||||
|
||||
/**
|
||||
* 单独配置 Server 端:查询数据 getData 地址
|
||||
*/
|
||||
public String getDataUrl = "/sso/getData";
|
||||
|
||||
/**
|
||||
* 配置当前 Client 端的登录地址(为空时自动获取)
|
||||
*/
|
||||
@ -75,6 +75,11 @@ public class SaSsoClientConfig implements Serializable {
|
||||
*/
|
||||
public String currSsoLogoutCall;
|
||||
|
||||
/**
|
||||
* 是否打开模式三(此值为 true 时将使用 http 请求校验 ticket 值)
|
||||
*/
|
||||
public Boolean isHttp = false;
|
||||
|
||||
/**
|
||||
* 是否打开单点注销功能 (为 true 时,接收单点注销回调消息推送)
|
||||
*/
|
||||
@ -85,18 +90,13 @@ public class SaSsoClientConfig implements Serializable {
|
||||
*/
|
||||
public Boolean regLogoutCall = false;
|
||||
|
||||
/**
|
||||
* 是否打开模式三(此值为 true 时将使用 http 请求校验 ticket 值)
|
||||
*/
|
||||
public Boolean isHttp = false;
|
||||
|
||||
/**
|
||||
* API 调用签名秘钥
|
||||
*/
|
||||
public String secretKey;
|
||||
|
||||
/**
|
||||
* 是否校验参数签名(方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
* 是否校验参数签名(为 false 时暂时关闭参数签名校验,此为方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
*/
|
||||
public Boolean isCheckSign = true;
|
||||
|
||||
@ -104,28 +104,28 @@ public class SaSsoClientConfig implements Serializable {
|
||||
// 额外添加的一些函数
|
||||
|
||||
/**
|
||||
* @return 获取拼接url:Server 端单点登录授权地址
|
||||
* @return 获取拼接 url:Server 端单点登录授权地址
|
||||
*/
|
||||
public String splicingAuthUrl() {
|
||||
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getAuthUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 获取拼接url:Server 端查询数据 getData 地址
|
||||
* @return 获取拼接 url:Server 端查询数据 getData 地址
|
||||
*/
|
||||
public String splicingGetDataUrl() {
|
||||
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getGetDataUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 获取拼接url:Server 端单点注销地址
|
||||
* @return 获取拼接 url:Server 端单点注销地址
|
||||
*/
|
||||
public String splicingSloUrl() {
|
||||
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getSloUrl());
|
||||
public String splicingSignoutUrl() {
|
||||
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getSignoutUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 获取拼接url:单独配置 Server 端推送消息地址
|
||||
* @return 获取拼接 url:单独配置 Server 端推送消息地址
|
||||
*/
|
||||
public String splicingPushUrl() {
|
||||
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getPushUrl());
|
||||
@ -153,14 +153,14 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 是否打开单点注销功能
|
||||
* @return 是否打开单点注销功能 (为 true 时,接收单点注销回调消息推送)
|
||||
*/
|
||||
public Boolean getIsSlo() {
|
||||
return isSlo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isSlo 是否打开单点注销功能
|
||||
* @param isSlo 是否打开单点注销功能 (为 true 时,接收单点注销回调消息推送)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientConfig setIsSlo(Boolean isSlo) {
|
||||
@ -169,14 +169,14 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return isHttp 是否打开模式三(此值为 true 时将使用 http 请求:校验ticket值、单点注销、拉取数据getData)
|
||||
* @return isHttp 是否打开模式三(此值为 true 时将使用 http 请求校验 ticket 值)
|
||||
*/
|
||||
public Boolean getIsHttp() {
|
||||
return isHttp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isHttp 是否打开模式三(此值为 true 时将使用 http 请求:校验ticket值、单点注销、拉取数据getData)
|
||||
* @param isHttp 是否打开模式三(此值为 true 时将使用 http 请求校验 ticket 值)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientConfig setIsHttp(Boolean isHttp) {
|
||||
@ -185,14 +185,18 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 当前 Client 名称标识,用于和 ticket 码的互相锁定
|
||||
* 当前 Client 标识(非必填,不填时代表当前应用是一个匿名应用)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param client 当前 Client 名称标识,用于和 ticket 码的互相锁定
|
||||
* 当前 Client 标识(非必填,不填时代表当前应用是一个匿名应用)
|
||||
*
|
||||
* @param client /
|
||||
*/
|
||||
public SaSsoClientConfig setClient(String client) {
|
||||
this.client = client;
|
||||
@ -200,14 +204,14 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 配置的 Server 端单点登录授权地址
|
||||
* @return 单独配置 Server 端:单点登录授权地址
|
||||
*/
|
||||
public String getAuthUrl() {
|
||||
return authUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authUrl 配置 Server 端单点登录授权地址
|
||||
* @param authUrl 单独配置 Server 端:单点登录授权地址
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientConfig setAuthUrl(String authUrl) {
|
||||
@ -216,14 +220,14 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server 端查询数据 getData 地址
|
||||
* @return 单独配置 Server 端:查询数据 getData 地址
|
||||
*/
|
||||
public String getGetDataUrl() {
|
||||
return getDataUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param getDataUrl 配置 Server 端查询数据 getData 地址
|
||||
* @param getDataUrl 单独配置 Server 端:查询数据 getData 地址
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientConfig setGetDataUrl(String getDataUrl) {
|
||||
@ -232,23 +236,23 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 配置 Server 端单点注销地址
|
||||
* @return 单独配置 Server 端:单点注销地址
|
||||
*/
|
||||
public String getSloUrl() {
|
||||
return sloUrl;
|
||||
public String getSignoutUrl() {
|
||||
return signoutUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sloUrl 配置 Server 端单点注销地址
|
||||
* @param signoutUrl 单独配置 Server 端:单点注销地址
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientConfig setSloUrl(String sloUrl) {
|
||||
this.sloUrl = sloUrl;
|
||||
public SaSsoClientConfig setSignoutUrl(String signoutUrl) {
|
||||
this.signoutUrl = signoutUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 单独配置 Server 端推送消息地址
|
||||
* 获取 单独配置 Server 端:推送消息地址
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
@ -257,7 +261,7 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 单独配置 Server 端推送消息地址
|
||||
* 设置 单独配置 Server 端:推送消息地址
|
||||
*
|
||||
* @param pushUrl /
|
||||
* @return 对象自身
|
||||
@ -300,14 +304,18 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 配置的 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、getDataUrl、sloUrl 属性前面,用以简化各种 url 配置
|
||||
* 配置 SSO Server 端主机总地址
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getServerUrl() {
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serverUrl 配置 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、getDataUrl、sloUrl 属性前面,用以简化各种 url 配置
|
||||
* 配置 SSO Server 端主机总地址
|
||||
*
|
||||
* @param serverUrl /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientConfig setServerUrl(String serverUrl) {
|
||||
@ -336,7 +344,7 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 是否校验参数签名(方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
* 获取 是否校验参数签名(为 false 时暂时关闭参数签名校验,此为方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
*
|
||||
* @return isCheckSign 是否校验参数签名(方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
*/
|
||||
@ -345,7 +353,7 @@ public class SaSsoClientConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 是否校验参数签名(方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
* 设置 是否校验参数签名(为 false 时暂时关闭参数签名校验,此为方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
*
|
||||
* @param isCheckSign 是否校验参数签名(方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
*/
|
||||
@ -381,8 +389,9 @@ public class SaSsoClientConfig implements Serializable {
|
||||
+ ", client=" + client
|
||||
+ ", serverUrl=" + serverUrl
|
||||
+ ", authUrl=" + authUrl
|
||||
+ ", signoutUrl=" + signoutUrl
|
||||
+ ", pushUrl=" + pushUrl
|
||||
+ ", getDataUrl=" + getDataUrl
|
||||
+ ", sloUrl=" + sloUrl
|
||||
+ ", currSsoLogin=" + currSsoLogin
|
||||
+ ", currSsoLogoutCall=" + currSsoLogoutCall
|
||||
+ ", isHttp=" + isHttp
|
||||
|
@ -16,6 +16,8 @@
|
||||
package cn.dev33.satoken.sso.config;
|
||||
|
||||
|
||||
import cn.dev33.satoken.sso.error.SaSsoErrorCode;
|
||||
import cn.dev33.satoken.sso.exception.SaSsoException;
|
||||
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
@ -23,29 +25,29 @@ import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 客户端信息配置
|
||||
* Sa-Token SSO 客户端信息配置 (在 Server 端配置允许接入的 Client 信息)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.42.0
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public class SaSsoClientModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6541180061782004705L;
|
||||
|
||||
/**
|
||||
* 当前 Client 名称标识,用于和 ticket 码的互相锁定
|
||||
* Client 名称标识
|
||||
*/
|
||||
public String client;
|
||||
|
||||
/**
|
||||
* 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
|
||||
* 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的 URL 将禁止下放 ticket )
|
||||
*/
|
||||
public String allowUrl = "*";
|
||||
|
||||
/**
|
||||
* 是否打开模式三(此值为 true 时使用 http 调用方式进行消息通知)
|
||||
* 是否接收推送消息
|
||||
*/
|
||||
public Boolean isHttp = false;
|
||||
public Boolean isPush = false;
|
||||
|
||||
/**
|
||||
* 是否打开单点注销功能
|
||||
@ -63,7 +65,7 @@ public class SaSsoClientModel implements Serializable {
|
||||
public String serverUrl;
|
||||
|
||||
/**
|
||||
* 此 Client 端推送消息的地址
|
||||
* 此 Client 端推送消息的地址 (如不配置,默认根据 serverUrl + '/sso/pushC' 进行拼接)
|
||||
*/
|
||||
public String pushUrl = "/sso/pushC";
|
||||
|
||||
@ -85,8 +87,12 @@ public class SaSsoClientModel implements Serializable {
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String splicingNoticeUrl() {
|
||||
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getPushUrl());
|
||||
public String splicingPushUrl() {
|
||||
String _pushUrl = SaFoxUtil.spliceTwoUrl(getServerUrl(), getPushUrl());
|
||||
if ( ! SaFoxUtil.isUrl(_pushUrl)) {
|
||||
throw new SaSsoException("应用 [" + getClient() + "] 推送地址无效:" + _pushUrl).setCode(SaSsoErrorCode.CODE_30023);
|
||||
}
|
||||
return _pushUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,22 +100,22 @@ public class SaSsoClientModel implements Serializable {
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public boolean isValidNoticeUrl() {
|
||||
return SaFoxUtil.isUrl(splicingNoticeUrl());
|
||||
public boolean isValidPushUrl() {
|
||||
return SaFoxUtil.isUrl(splicingPushUrl());
|
||||
}
|
||||
|
||||
|
||||
// get set
|
||||
|
||||
/**
|
||||
* @return 当前 Client 名称标识
|
||||
* @return Client 名称标识
|
||||
*/
|
||||
public String getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param client 当前 Client 名称标识
|
||||
* @param client Client 名称标识
|
||||
*/
|
||||
public SaSsoClientModel setClient(String client) {
|
||||
this.client = client;
|
||||
@ -117,14 +123,14 @@ public class SaSsoClientModel implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
|
||||
* @return 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的 URL 将禁止下放 ticket )
|
||||
*/
|
||||
public String getAllowUrl() {
|
||||
return allowUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param allowUrl 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
|
||||
* @param allowUrl 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的 URL 将禁止下放 ticket )
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientModel setAllowUrl(String allowUrl) {
|
||||
@ -140,16 +146,16 @@ public class SaSsoClientModel implements Serializable {
|
||||
/**
|
||||
* @return isHttp 是否打开模式三
|
||||
*/
|
||||
public Boolean getIsHttp() {
|
||||
return isHttp;
|
||||
public Boolean getIsPush() {
|
||||
return isPush;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isHttp 是否打开模式三
|
||||
* @param isPush 是否打开模式三
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoClientModel setIsHttp(Boolean isHttp) {
|
||||
this.isHttp = isHttp;
|
||||
public SaSsoClientModel setIsPush(Boolean isPush) {
|
||||
this.isPush = isPush;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -210,16 +216,16 @@ public class SaSsoClientModel implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 此 Client 端推送消息的地址
|
||||
* 获取 此 Client 端推送消息的地址 (如不配置,默认根据 serverUrl + '/sso/pushC' 进行拼接)
|
||||
*
|
||||
* @return noticeUrl 此 Client 端推送消息的地址
|
||||
* @return /
|
||||
*/
|
||||
public String getPushUrl() {
|
||||
return this.pushUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 此 Client 端推送消息的地址
|
||||
* 设置 此 Client 端推送消息的地址 (如不配置,默认根据 serverUrl + '/sso/pushC' 进行拼接)
|
||||
*
|
||||
* @param pushUrl 此 Client 端推送消息的地址
|
||||
* @return 对象自身
|
||||
@ -235,7 +241,7 @@ public class SaSsoClientModel implements Serializable {
|
||||
+ "client=" + client
|
||||
+ ", allowUrl=" + allowUrl
|
||||
+ ", isSlo=" + isSlo
|
||||
+ ", isHttp=" + isHttp
|
||||
+ ", isPush=" + isPush
|
||||
+ ", secretKey=" + secretKey
|
||||
+ ", serverUrl=" + serverUrl
|
||||
+ ", pushUrl=" + pushUrl
|
||||
|
@ -25,7 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 单点登录模块 配置类 (Server端)
|
||||
* Sa-Token SSO Server 端 配置类
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.38.0
|
||||
@ -43,7 +43,7 @@ public class SaSsoServerConfig implements Serializable {
|
||||
public String mode = "";
|
||||
|
||||
/**
|
||||
* Ticket有效期 (单位: 秒)
|
||||
* ticket 有效期 (单位: 秒)
|
||||
*/
|
||||
public long ticketTimeout = 60 * 5;
|
||||
|
||||
@ -53,7 +53,7 @@ public class SaSsoServerConfig implements Serializable {
|
||||
public String homeRoute;
|
||||
|
||||
/**
|
||||
* 是否打开单点注销功能
|
||||
* 是否打开单点注销功能 (为 true 时接收 client 端推送的单点注销消息)
|
||||
*/
|
||||
public Boolean isSlo = true;
|
||||
|
||||
@ -98,7 +98,7 @@ public class SaSsoServerConfig implements Serializable {
|
||||
// 额外方法
|
||||
|
||||
/**
|
||||
* 以数组形式写入允许的授权回调地址
|
||||
* 以数组形式写入允许的授权回调地址 (不在此列表中的URL将禁止下放ticket) (匿名 client 使用)
|
||||
* @param url 所有集合
|
||||
* @return 对象自身
|
||||
*/
|
||||
@ -139,14 +139,14 @@ public class SaSsoServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Ticket有效期 (单位: 秒)
|
||||
* @return ticket 有效期 (单位: 秒)
|
||||
*/
|
||||
public long getTicketTimeout() {
|
||||
return ticketTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ticketTimeout Ticket有效期 (单位: 秒)
|
||||
* @param ticketTimeout ticket 有效期 (单位: 秒)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoServerConfig setTicketTimeout(long ticketTimeout) {
|
||||
@ -192,14 +192,14 @@ public class SaSsoServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 是否打开单点注销功能
|
||||
* @return 是否打开单点注销功能 (为 true 时接收 client 端推送的单点注销消息)
|
||||
*/
|
||||
public Boolean getIsSlo() {
|
||||
return isSlo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isSlo 是否打开单点注销功能
|
||||
* @param isSlo 是否打开单点注销功能 (为 true 时接收 client 端推送的单点注销消息)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoServerConfig setIsSlo(Boolean isSlo) {
|
||||
|
@ -77,4 +77,7 @@ public interface SaSsoErrorCode {
|
||||
/** 无效的消息推送地址 */
|
||||
int CODE_30023 = 30023;
|
||||
|
||||
/** SSO 消息里缺少指定的参数 */
|
||||
int CODE_30024 = 30024;
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import cn.dev33.satoken.util.SaResult;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* 函数式接口:SSO-Server端:在校验 ticket 后,给 sso-client 端追加返回信息的函数
|
||||
* 函数式接口:sso-server 端:在校验 ticket 后,给 sso-client 端追加返回信息的函数
|
||||
*
|
||||
* <p> 参数:loginId, SaResult 响应参数对象 </p>
|
||||
* <p> 返回:SaResult 响应参数对象 </p>
|
||||
|
@ -18,7 +18,7 @@ package cn.dev33.satoken.sso.function;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* 函数式接口:SSO-Server端:登录处理函数
|
||||
* 函数式接口:sso-server 端:登录处理函数
|
||||
*
|
||||
* <p> 参数:账号、密码 </p>
|
||||
* <p> 返回:登录结果 </p>
|
||||
|
@ -18,7 +18,7 @@ package cn.dev33.satoken.sso.function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 函数式接口:SSO-Server端:未登录时返回的View
|
||||
* 函数式接口:sso-server 端:未登录时返回的 View
|
||||
*
|
||||
* <p> 参数:无 </p>
|
||||
* <p> 返回:未登录时的 View 视图 </p>
|
||||
|
@ -18,7 +18,7 @@ package cn.dev33.satoken.sso.function;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 函数式接口:发送Http请求的处理函数
|
||||
* 函数式接口:发送 Http 请求的处理函数
|
||||
*
|
||||
* <p> 参数:要请求的url </p>
|
||||
* <p> 返回:请求结果 </p>
|
||||
|
@ -18,7 +18,7 @@ package cn.dev33.satoken.sso.function;
|
||||
import cn.dev33.satoken.sso.model.SaCheckTicketResult;
|
||||
|
||||
/**
|
||||
* 函数式接口:SSO-Client端:自定义校验 ticket 返回值的处理逻辑 (每次从认证中心获取校验 ticket 的结果后调用)
|
||||
* 函数式接口:sso-client 端:自定义校验 ticket 返回值的处理逻辑 (每次从认证中心获取校验 ticket 的结果后调用)
|
||||
*
|
||||
* <p> 参数:loginId, back </p>
|
||||
* <p> 返回:返回给前端的值 </p>
|
||||
|
@ -26,7 +26,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 消息 Model
|
||||
* SSO 消息 Model
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
@ -108,4 +108,19 @@ public class SaSsoMessage extends LinkedHashMap<String, Object> implements SaSet
|
||||
return this;
|
||||
}
|
||||
|
||||
// -----------
|
||||
|
||||
/**
|
||||
* 获取一个值 (此值必须存在,否则抛出异常 )
|
||||
* @param key 键
|
||||
* @return 参数值
|
||||
*/
|
||||
public Object getValueNotNull(String key) {
|
||||
Object value = get(key);
|
||||
if(SaFoxUtil.isEmpty(value)) {
|
||||
throw new SaSsoException("缺少参数:" + key).setCode(SaSsoErrorCode.CODE_30024);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 消息处理器持有者
|
||||
* SSO 消息处理器 - 持有器
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
@ -33,7 +33,7 @@ import java.util.Map;
|
||||
public class SaSsoMessageHolder {
|
||||
|
||||
/**
|
||||
* 所有消息处理器的集合
|
||||
* 所有已注册的消息处理器
|
||||
*/
|
||||
public final Map<String, SaSsoMessageHandle> messageHandleMap = new LinkedHashMap<>();
|
||||
|
||||
@ -61,6 +61,7 @@ public class SaSsoMessageHolder {
|
||||
* 添加指定类型的消息处理器
|
||||
*
|
||||
* @param handle /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoMessageHolder addHandle(SaSsoMessageHandle handle) {
|
||||
messageHandleMap.put(handle.getHandlerType(), handle);
|
||||
@ -81,7 +82,7 @@ public class SaSsoMessageHolder {
|
||||
*
|
||||
* @param ssoTemplate /
|
||||
* @param message /
|
||||
* @return /
|
||||
* @return 处理结果
|
||||
*/
|
||||
public Object handleMessage(SaSsoTemplate ssoTemplate, SaSsoMessage message) {
|
||||
SaSsoMessageHandle handle = messageHandleMap.get(message.getType());
|
||||
|
@ -20,7 +20,7 @@ import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 消息 处理器
|
||||
* SSO 消息处理器 - 父接口
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
@ -35,7 +35,7 @@ public interface SaSsoMessageHandle {
|
||||
String getHandlerType();
|
||||
|
||||
/**
|
||||
* 执行方法
|
||||
* 具体要执行的处理方法
|
||||
*
|
||||
* @param ssoTemplate /
|
||||
* @param message /
|
||||
|
@ -29,7 +29,7 @@ import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 消息 处理器 - sso-client 端:处理 单点注销回调 的请求
|
||||
* SSO 消息处理器 - sso-client 端:处理 单点注销回调 的请求
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
@ -53,27 +53,28 @@ public class SaSsoMessageLogoutCallHandle implements SaSsoMessageHandle {
|
||||
* @return /
|
||||
*/
|
||||
public Object handle(SaSsoTemplate ssoTemplate, SaSsoMessage message) {
|
||||
|
||||
// 1、获取对象
|
||||
SaSsoClientTemplate ssoClientTemplate = (SaSsoClientTemplate) ssoTemplate;
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
ParamName paramName = ssoClientTemplate.paramName;
|
||||
|
||||
// 2、判断当前应用是否开启单点注销功能
|
||||
if( ! ssoClientTemplate.getClientConfig().getIsSlo()) {
|
||||
return SaResult.error("当前 sso-client 端未开启单点注销功能");
|
||||
}
|
||||
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
ParamName paramName = ssoClientTemplate.paramName;
|
||||
|
||||
// 获取参数
|
||||
Object loginId = req.getParamNotNull(paramName.loginId);
|
||||
// 3、获取参数
|
||||
Object loginId = message.getValueNotNull(paramName.loginId);
|
||||
loginId = ssoClientTemplate.strategy.convertCenterIdToLoginId.run(loginId);
|
||||
String deviceId = message.getString(paramName.deviceId);
|
||||
|
||||
// 注销当前应用端会话
|
||||
// 4、注销当前应用端会话
|
||||
stpLogic.logout(loginId, new SaLogoutParameter()
|
||||
.setDeviceId(deviceId)
|
||||
);
|
||||
|
||||
// 响应
|
||||
// 5、响应
|
||||
return SaResult.ok("单点注销回调成功");
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,6 @@
|
||||
package cn.dev33.satoken.sso.message.handle.server;
|
||||
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.context.model.SaRequest;
|
||||
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
|
||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||
import cn.dev33.satoken.sso.message.handle.SaSsoMessageHandle;
|
||||
import cn.dev33.satoken.sso.model.TicketModel;
|
||||
@ -30,7 +27,7 @@ import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 消息 处理器 - sso-server 端:处理校验 ticket 的请求
|
||||
* SSO 消息处理器 - sso-server 端:处理校验 ticket 的请求
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
@ -54,38 +51,23 @@ public class SaSsoMessageCheckTicketHandle implements SaSsoMessageHandle {
|
||||
* @return /
|
||||
*/
|
||||
public Object handle(SaSsoTemplate ssoTemplate, SaSsoMessage message) {
|
||||
|
||||
// 1、获取对象
|
||||
SaSsoServerTemplate ssoServerTemplate = (SaSsoServerTemplate) ssoTemplate;
|
||||
ParamName paramName = ssoServerTemplate.paramName;
|
||||
|
||||
// 1、获取参数
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaSsoServerConfig ssoServerConfig = ssoServerTemplate.getServerConfig();
|
||||
StpLogic stpLogic = ssoServerTemplate.getStpLogic();
|
||||
String client = req.getParam(paramName.client);
|
||||
String ticket = req.getParamNotNull(paramName.ticket);
|
||||
String sloCallback = req.getParam(paramName.ssoLogoutCall);
|
||||
String client = message.getString(paramName.client);
|
||||
String ticket = message.getValueNotNull(paramName.ticket).toString();
|
||||
String sloCallback = message.getString(paramName.ssoLogoutCall);
|
||||
|
||||
|
||||
// 2、校验提供的client是否为非法字符
|
||||
if(SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
||||
return SaResult.error("无效 client 标识:" + client);
|
||||
}
|
||||
|
||||
// 3、校验签名
|
||||
// if(ssoServerConfig.getIsCheckSign()) {
|
||||
// ssoServerTemplate.getSignTemplate(client).checkRequest(req, paramName.client, paramName.ticket, paramName.ssoLogoutCall);
|
||||
// } else {
|
||||
// SaSsoManager.printNoCheckSignWarningByRuntime();
|
||||
// }
|
||||
|
||||
// 4、校验ticket,获取 loginId
|
||||
// 2、校验ticket,获取 loginId
|
||||
TicketModel ticketModel = ssoServerTemplate.checkTicketParamAndDelete(ticket, client);
|
||||
Object loginId = ticketModel.getLoginId();
|
||||
|
||||
// 5、注册此客户端的单点注销回调URL
|
||||
// 3、注册此客户端的登录信息
|
||||
ssoServerTemplate.registerSloCallbackUrl(loginId, client, sloCallback);
|
||||
|
||||
// 6、给 client 端响应结果
|
||||
// 4、给 client 端响应结果
|
||||
SaResult result = SaResult.ok();
|
||||
result.setData(loginId); // 兼容历史版本
|
||||
result.set(paramName.loginId, loginId);
|
||||
@ -93,7 +75,6 @@ public class SaSsoMessageCheckTicketHandle implements SaSsoMessageHandle {
|
||||
result.set(paramName.deviceId, stpLogic.getLoginDeviceIdByToken(ticketModel.getTokenValue()));
|
||||
result.set(paramName.remainTokenTimeout, stpLogic.getTokenTimeout(ticketModel.getTokenValue()));
|
||||
result.set(paramName.remainSessionTimeout, stpLogic.getSessionTimeoutByLoginId(loginId));
|
||||
|
||||
result = ssoServerTemplate.strategy.checkTicketAppendData.apply(loginId, result);
|
||||
return result;
|
||||
}
|
||||
|
@ -16,8 +16,6 @@
|
||||
package cn.dev33.satoken.sso.message.handle.server;
|
||||
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.context.model.SaRequest;
|
||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||
import cn.dev33.satoken.sso.message.handle.SaSsoMessageHandle;
|
||||
import cn.dev33.satoken.sso.name.ParamName;
|
||||
@ -28,7 +26,7 @@ import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 消息 处理器 - sso-server 端:处理 单点注销 的请求
|
||||
* SSO 消息处理器 - sso-server 端:处理 单点注销 的请求
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
@ -52,24 +50,25 @@ public class SaSsoMessageSignoutHandle implements SaSsoMessageHandle {
|
||||
* @return /
|
||||
*/
|
||||
public Object handle(SaSsoTemplate ssoTemplate, SaSsoMessage message) {
|
||||
|
||||
// 1、获取对象
|
||||
SaSsoServerTemplate ssoServerTemplate = (SaSsoServerTemplate) ssoTemplate;
|
||||
ParamName paramName = ssoServerTemplate.paramName;
|
||||
|
||||
// 2、判断当前是否开启了全局单点注销功能
|
||||
if( ! ssoServerTemplate.getServerConfig().getIsSlo()) {
|
||||
return SaResult.error("当前 sso-server 端未开启单点注销功能");
|
||||
}
|
||||
|
||||
// 获取参数
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
String loginId = req.getParam(paramName.loginId);
|
||||
String deviceId = req.getParam(paramName.deviceId);
|
||||
// 3、获取参数
|
||||
Object loginId = message.get(paramName.loginId);
|
||||
String deviceId = message.getString(paramName.deviceId);
|
||||
|
||||
// step.2 单点注销
|
||||
SaLogoutParameter logoutParameter = ssoServerTemplate.getStpLogic().createSaLogoutParameter()
|
||||
.setDeviceId(deviceId);
|
||||
// 4、单点注销
|
||||
SaLogoutParameter logoutParameter = ssoServerTemplate.getStpLogic().createSaLogoutParameter().setDeviceId(deviceId);
|
||||
ssoServerTemplate.ssoLogout(loginId, logoutParameter);
|
||||
|
||||
// 响应
|
||||
// 5、响应
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
|
@ -47,12 +47,9 @@ public class SaCheckTicketResult implements Serializable {
|
||||
/** 此账号在认证中心的 loginId */
|
||||
public Object centerId;
|
||||
|
||||
/** 从 sso-server 返回的所有参数 */
|
||||
/** 从 sso-server 返回的原生所有参数 */
|
||||
public SaResult result;
|
||||
|
||||
public SaCheckTicketResult() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaCheckTicketResult{" +
|
||||
|
@ -21,7 +21,7 @@ import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 应用信息
|
||||
* Sa-Token SSO 应用信息(注册在 SaSession 上的已登录应用信息列表)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.38.0
|
||||
@ -45,13 +45,8 @@ public class SaSsoClientInfo implements Serializable {
|
||||
*/
|
||||
public String client;
|
||||
|
||||
// /**
|
||||
// * 此次登录 token 值
|
||||
// */
|
||||
// public String tokenValue;
|
||||
|
||||
/**
|
||||
* 单点注销回调url
|
||||
* 单点注销回调 url
|
||||
*/
|
||||
public String sloCallbackUrl;
|
||||
|
||||
@ -80,6 +75,8 @@ public class SaSsoClientInfo implements Serializable {
|
||||
}
|
||||
|
||||
|
||||
// get set
|
||||
|
||||
/**
|
||||
* 获取 此 client 登录模式(1=模式一,2=模式二,3=模式三)
|
||||
*
|
||||
@ -120,26 +117,6 @@ public class SaSsoClientInfo implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取 此次登录 token 值
|
||||
// *
|
||||
// * @return tokenValue 此次登录 token 值
|
||||
// */
|
||||
// public String getTokenValue() {
|
||||
// return this.tokenValue;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 设置 此次登录 token 值
|
||||
// *
|
||||
// * @param tokenValue 此次登录 token 值
|
||||
// * @return /
|
||||
// */
|
||||
// public SaSsoClientModel setTokenValue(String tokenValue) {
|
||||
// this.tokenValue = tokenValue;
|
||||
// return this;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取 单点注销回调url
|
||||
*
|
||||
@ -205,7 +182,6 @@ public class SaSsoClientInfo implements Serializable {
|
||||
return "SaSsoClientModel{" +
|
||||
"mode=" + mode +
|
||||
", client='" + client + '\'' +
|
||||
// ", tokenValue='" + tokenValue + '\'' +
|
||||
", sloCallbackUrl='" + sloCallbackUrl + '\'' +
|
||||
", regTime=" + regTime +
|
||||
", index=" + index +
|
||||
|
@ -37,11 +37,6 @@ public class TicketModel implements Serializable {
|
||||
*/
|
||||
public String client;
|
||||
|
||||
// /**
|
||||
// * 设备 id
|
||||
// */
|
||||
// public String deviceId;
|
||||
|
||||
/**
|
||||
* 对应 loginId
|
||||
*/
|
||||
|
@ -32,7 +32,7 @@ public class ApiName {
|
||||
/** SSO-Server端:校验ticket 获取账号id */
|
||||
public String ssoCheckTicket = "/sso/checkTicket";
|
||||
|
||||
/** SSO-Server端:接受推送消息 */
|
||||
/** SSO-Server端:接收推送消息 */
|
||||
public String ssoPushS = "/sso/pushS";
|
||||
|
||||
/** SSO-Server端:获取userinfo */
|
||||
@ -53,11 +53,11 @@ public class ApiName {
|
||||
/** SSO-Client端:单点注销的回调 */
|
||||
public String ssoLogoutCall = "/sso/logoutCall";
|
||||
|
||||
/** SSO-Client端:接受推送消息 */
|
||||
/** SSO-Client端:接收推送消息 */
|
||||
public String ssoPushC = "/sso/pushC";
|
||||
|
||||
/**
|
||||
* 批量修改path,新增固定前缀
|
||||
* 批量修改 path,新增固定前缀
|
||||
* @param prefix 示例值:/sso-user、/sso-admin
|
||||
* @return 对象自身
|
||||
*/
|
||||
@ -77,7 +77,7 @@ public class ApiName {
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量修改path,替换掉 /sso 固定前缀
|
||||
* 批量修改 path,替换掉 /sso 固定前缀
|
||||
* @param prefix 示例值:/sso-user、/sso-admin
|
||||
* @return 对象自身
|
||||
*/
|
||||
@ -106,6 +106,7 @@ public class ApiName {
|
||||
", ssoPushS='" + ssoPushS + '\'' +
|
||||
", ssoUserinfo='" + ssoUserinfo + '\'' +
|
||||
", ssoSignout='" + ssoSignout + '\'' +
|
||||
", ssoIsLogin='" + ssoIsLogin + '\'' +
|
||||
", ssoLogin='" + ssoLogin + '\'' +
|
||||
", ssoLogout='" + ssoLogout + '\'' +
|
||||
", ssoLogoutCall='" + ssoLogoutCall + '\'' +
|
||||
|
@ -23,40 +23,40 @@ package cn.dev33.satoken.sso.name;
|
||||
*/
|
||||
public class ParamName {
|
||||
|
||||
/** redirect参数名称 */
|
||||
/** redirect 参数名称 */
|
||||
public String redirect = "redirect";
|
||||
|
||||
/** ticket参数名称 */
|
||||
/** ticket 参数名称 */
|
||||
public String ticket = "ticket";
|
||||
|
||||
/** back参数名称 */
|
||||
/** back 参数名称 */
|
||||
public String back = "back";
|
||||
|
||||
/** mode参数名称 */
|
||||
/** mode 参数名称 */
|
||||
public String mode = "mode";
|
||||
|
||||
/** loginId参数名称 */
|
||||
/** 账号 id */
|
||||
public String loginId = "loginId";
|
||||
|
||||
/** client参数名称 */
|
||||
/** client 应用标识 */
|
||||
public String client = "client";
|
||||
|
||||
/** tokenName 参数 */
|
||||
/** token 名称 */
|
||||
public String tokenName = "tokenName";
|
||||
|
||||
/** tokenValue 参数 */
|
||||
/** token 值 */
|
||||
public String tokenValue = "tokenValue";
|
||||
|
||||
/** deviceId 参数名称 */
|
||||
/** 设备 id */
|
||||
public String deviceId = "deviceId";
|
||||
|
||||
/** secretkey参数名称 */
|
||||
/** 接口参数签名秘钥 */
|
||||
public String secretkey = "secretkey";
|
||||
|
||||
/** Client端单点注销时-回调URL 参数名称 */
|
||||
/** Client 端单点注销时 - 回调 URL 参数名称 */
|
||||
public String ssoLogoutCall = "ssoLogoutCall";
|
||||
|
||||
/** 是否为超过 maxRegClient 的自动注销 */
|
||||
/** 是否为超过 maxRegClient 触发的自动注销 */
|
||||
public String autoLogout = "autoLogout";
|
||||
|
||||
public String name = "name";
|
||||
@ -72,13 +72,8 @@ public class ParamName {
|
||||
/** token 剩余有效期 参数名称 */
|
||||
public String remainTokenTimeout = "remainTokenTimeout";
|
||||
|
||||
/** singleDeviceIdLogout 参数 */
|
||||
/** 是否单设备 id 注销 */
|
||||
public String singleDeviceIdLogout = "singleDeviceIdLogout";
|
||||
|
||||
public String isLogin = "isLogin";
|
||||
public String authUrl = "authUrl";
|
||||
public String redirectUrl = "redirectUrl";
|
||||
public String currSsoLoginUrl = "currSsoLoginUrl";
|
||||
|
||||
|
||||
}
|
||||
|
@ -70,22 +70,22 @@ public class SaSsoClientProcessor {
|
||||
|
||||
// ------------------ 路由分发 ------------------
|
||||
|
||||
// ---------- SSO-Client端:登录地址
|
||||
// sso-client:登录地址
|
||||
if(req.isPath(apiName.ssoLogin)) {
|
||||
return ssoLogin();
|
||||
}
|
||||
|
||||
// ---------- SSO-Client端:单点注销
|
||||
// sso-client:单点注销
|
||||
if(req.isPath(apiName.ssoLogout)) {
|
||||
return ssoLogout();
|
||||
}
|
||||
|
||||
// ---------- SSO-Client端:接收消息推送
|
||||
// sso-client:接收消息推送
|
||||
if(req.isPath(apiName.ssoPushC)) {
|
||||
return ssoPushC();
|
||||
}
|
||||
|
||||
// ---------- SSO-Client端:单点注销的回调 [模式三]
|
||||
// sso-client:单点注销的回调
|
||||
if(req.isPath(apiName.ssoLogoutCall) && cfg.getRegLogoutCall()) {
|
||||
return ssoLogoutCall();
|
||||
}
|
||||
@ -101,55 +101,18 @@ public class SaSsoClientProcessor {
|
||||
public Object ssoLogin() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
SaSsoClientConfig cfg = ssoClientTemplate.getClientConfig();
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
ApiName apiName = ssoClientTemplate.apiName;
|
||||
ParamName paramName = ssoClientTemplate.paramName;
|
||||
|
||||
// 获取参数
|
||||
String back = req.getParam(paramName.back, "/");
|
||||
String ticket = req.getParam(paramName.ticket);
|
||||
|
||||
/*
|
||||
* 此时有两种情况:
|
||||
* 情况1:ticket无值,说明此请求是Client端访问,需要重定向至SSO认证中心
|
||||
* 情况2:ticket有值,说明此请求从SSO认证中心重定向而来,需要根据ticket进行登录
|
||||
* 情况1:ticket 无值,说明此请求是 sso-client 端访问,需要重定向至 sso-server 认证中心
|
||||
* 情况2:ticket 有值,说明此请求从 sso-server 认证中心重定向而来,需要根据 ticket 进行登录
|
||||
*/
|
||||
if(ticket == null) {
|
||||
// 如果当前Client端已经登录,则无需访问SSO认证中心,可以直接返回
|
||||
if(stpLogic.isLogin()) {
|
||||
return res.redirect(back);
|
||||
}
|
||||
|
||||
// 获取当前项目的 sso 登录地址
|
||||
// 全局配置了就是用全局的,否则使用当前请求的地址
|
||||
String currSsoLoginUrl;
|
||||
if(SaFoxUtil.isNotEmpty(cfg.getCurrSsoLogin())) {
|
||||
currSsoLoginUrl = cfg.getCurrSsoLogin();
|
||||
} else {
|
||||
currSsoLoginUrl = SaHolder.getRequest().getUrl();
|
||||
}
|
||||
// 构建url
|
||||
String serverAuthUrl = ssoClientTemplate.buildServerAuthUrl(currSsoLoginUrl, back);
|
||||
return res.redirect(serverAuthUrl);
|
||||
return _goServerAuth();
|
||||
} else {
|
||||
// 1、校验ticket,获取 loginId
|
||||
SaCheckTicketResult ctr = checkTicket(ticket, apiName.ssoLogin);
|
||||
ctr.centerId = ctr.loginId;
|
||||
ctr.loginId = ssoClientTemplate.strategy.convertCenterIdToLoginId.run(ctr.centerId);
|
||||
|
||||
// 2、如果开发者自定义了ticket结果值处理函数,则使用自定义的函数
|
||||
if(ssoClientTemplate.strategy.ticketResultHandle != null) {
|
||||
return ssoClientTemplate.strategy.ticketResultHandle.run(ctr, back);
|
||||
}
|
||||
|
||||
// 3、登录并重定向至back地址
|
||||
stpLogic.login(ctr.loginId, new SaLoginParameter()
|
||||
.setTimeout(ctr.remainTokenTimeout)
|
||||
.setDeviceId(ctr.deviceId)
|
||||
);
|
||||
return res.redirect(back);
|
||||
return _loginByTicket();
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,9 +125,10 @@ public class SaSsoClientProcessor {
|
||||
SaSsoClientConfig cfg = ssoClientTemplate.getClientConfig();
|
||||
|
||||
// 无论登录时选择的是模式二还是模式三
|
||||
// 在注销时都应该按照模式三的方法,通过 http 请求调用 sso-server 的单点注销接口来做到全端下线
|
||||
// 在注销时都应该按照模式三的方法,通过 http 请求调用 sso-server 的单点注销接口来做到全端下线
|
||||
// 如果按照模式二的方法注销,则会导致按照模式三登录的应用无法参与到单点注销环路中来
|
||||
if(cfg.getIsSlo()) {
|
||||
return ssoLogoutByMode3();
|
||||
return _ssoLogoutByMode3();
|
||||
}
|
||||
|
||||
// 默认返回
|
||||
@ -192,63 +156,6 @@ public class SaSsoClientProcessor {
|
||||
return ssoClientTemplate.handleMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO-Client端:单点注销 [模式二]
|
||||
* @return 处理结果
|
||||
*/
|
||||
public Object ssoLogoutByMode2() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
|
||||
// 开始处理
|
||||
if(stpLogic.isLogin()) {
|
||||
stpLogic.logout(stpLogic.getLoginId());
|
||||
}
|
||||
|
||||
// 返回
|
||||
return ssoLogoutBack(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO-Client端:单点注销 [模式三]
|
||||
* @return 处理结果
|
||||
*/
|
||||
public Object ssoLogoutByMode3() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
boolean singleDeviceIdLogout = req.isParam(ssoClientTemplate.paramName.singleDeviceIdLogout, "true");
|
||||
|
||||
// 如果未登录,则无需注销
|
||||
if( ! stpLogic.isLogin()) {
|
||||
return ssoLogoutBack(req, res);
|
||||
}
|
||||
|
||||
// 调用 sso-server 认证中心单点注销API
|
||||
SaLogoutParameter logoutParameter = stpLogic.createSaLogoutParameter();
|
||||
if(singleDeviceIdLogout) {
|
||||
logoutParameter.setDeviceId(stpLogic.getLoginDeviceId());
|
||||
}
|
||||
Object centerId = ssoClientTemplate.strategy.convertLoginIdToCenterId.run(stpLogic.getLoginId());
|
||||
SaSsoMessage message = ssoClientTemplate.buildSloMessage(centerId, logoutParameter);
|
||||
SaResult result = ssoClientTemplate.pushMessageAsSaResult(message);
|
||||
|
||||
// 校验响应状态码
|
||||
if(result.getCode() != null && SaResult.CODE_SUCCESS == result.getCode()) {
|
||||
// 极端场景下,sso-server 中心的单点注销可能并不会通知到此 client 端,所以这里需要再补一刀
|
||||
if(stpLogic.isLogin()) {
|
||||
stpLogic.logout();
|
||||
}
|
||||
return ssoLogoutBack(req, res);
|
||||
} else {
|
||||
// 将 sso-server 回应的消息作为异常抛出
|
||||
throw new SaSsoException(result.getMsg()).setCode(SaSsoErrorCode.CODE_30006);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO-Client端:单点注销的回调 [模式三]
|
||||
* @return 处理结果
|
||||
@ -265,8 +172,6 @@ public class SaSsoClientProcessor {
|
||||
Object loginId = req.getParamNotNull(paramName.loginId);
|
||||
loginId = ssoClientTemplate.strategy.convertCenterIdToLoginId.run(loginId);
|
||||
String deviceId = req.getParam(paramName.deviceId);
|
||||
// String client = req.getParam(paramName.client);
|
||||
// String autoLogout = req.getParam(paramName.autoLogout);
|
||||
|
||||
// 校验参数签名
|
||||
if(ssoConfig.getIsCheckSign()) {
|
||||
@ -283,7 +188,109 @@ public class SaSsoClientProcessor {
|
||||
return SaResult.ok("单点注销回调成功");
|
||||
}
|
||||
|
||||
// 工具方法
|
||||
// 次级方法
|
||||
|
||||
/**
|
||||
* 跳转去 sso-server 认证中心
|
||||
* @return /
|
||||
*/
|
||||
public Object _goServerAuth() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
SaSsoClientConfig cfg = ssoClientTemplate.getClientConfig();
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
ParamName paramName = ssoClientTemplate.paramName;
|
||||
|
||||
// 获取参数
|
||||
String back = req.getParam(paramName.back, "/");
|
||||
|
||||
// 如果当前 sso-client 端已经登录,则无需访问 SSO 认证中心,可以直接返回
|
||||
if(stpLogic.isLogin()) {
|
||||
return res.redirect(back);
|
||||
}
|
||||
|
||||
// 获取当前项目的 sso 登录中转页地址,形如:http://sso-client.com/sso/login
|
||||
// 全局配置了就是用全局的,否则使用当前请求的地址
|
||||
String currSsoLoginUrl = cfg.getCurrSsoLogin();
|
||||
if(SaFoxUtil.isEmpty(currSsoLoginUrl)) {
|
||||
currSsoLoginUrl = SaHolder.getRequest().getUrl();
|
||||
}
|
||||
// 构建最终授权地址 url,形如:http://sso-server.com/sso/auth?redirectUrl=http://sso-client.com/sso/login?back=http://sso-client.com
|
||||
String serverAuthUrl = ssoClientTemplate.buildServerAuthUrl(currSsoLoginUrl, back);
|
||||
return res.redirect(serverAuthUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据认证中心回传的 ticket 进行登录
|
||||
* @return /
|
||||
*/
|
||||
public Object _loginByTicket() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
ParamName paramName = ssoClientTemplate.paramName;
|
||||
ApiName apiName = ssoClientTemplate.apiName;
|
||||
|
||||
// 获取参数
|
||||
String back = req.getParam(paramName.back, "/");
|
||||
String ticket = req.getParam(paramName.ticket);
|
||||
|
||||
// 1、校验 ticket,获取 loginId 等数据
|
||||
SaCheckTicketResult ctr = checkTicket(ticket, apiName.ssoLogin);
|
||||
ctr.centerId = ctr.loginId;
|
||||
ctr.loginId = ssoClientTemplate.strategy.convertCenterIdToLoginId.run(ctr.centerId);
|
||||
|
||||
// 2、如果开发者自定义了 ticket 结果值处理函数,则使用自定义的函数
|
||||
if(ssoClientTemplate.strategy.ticketResultHandle != null) {
|
||||
return ssoClientTemplate.strategy.ticketResultHandle.run(ctr, back);
|
||||
}
|
||||
|
||||
// 3、登录并重定向至back地址
|
||||
stpLogic.login(ctr.loginId, new SaLoginParameter()
|
||||
.setTimeout(ctr.remainTokenTimeout)
|
||||
.setDeviceId(ctr.deviceId)
|
||||
);
|
||||
return res.redirect(back);
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO-Client端:单点注销 [模式三]
|
||||
* @return 处理结果
|
||||
*/
|
||||
public Object _ssoLogoutByMode3() {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
boolean singleDeviceIdLogout = req.isParam(ssoClientTemplate.paramName.singleDeviceIdLogout, "true");
|
||||
|
||||
// 如果未登录,则无需注销
|
||||
if( ! stpLogic.isLogin()) {
|
||||
return _ssoLogoutBack(req, res);
|
||||
}
|
||||
|
||||
// 向 sso-server 认证中心推送消息:单点注销
|
||||
SaLogoutParameter logoutParameter = stpLogic.createSaLogoutParameter();
|
||||
if(singleDeviceIdLogout) {
|
||||
logoutParameter.setDeviceId(stpLogic.getLoginDeviceId());
|
||||
}
|
||||
Object centerId = ssoClientTemplate.strategy.convertLoginIdToCenterId.run(stpLogic.getLoginId());
|
||||
SaSsoMessage message = ssoClientTemplate.buildSloMessage(centerId, logoutParameter);
|
||||
SaResult result = ssoClientTemplate.pushMessageAsSaResult(message);
|
||||
|
||||
// 如果 sso-server 响应的状态码非200,代表业务失败,将回应的 msg 字段作为异常抛出
|
||||
if(result.getCode() == null || SaResult.CODE_SUCCESS != result.getCode()) {
|
||||
throw new SaSsoException(result.getMsg()).setCode(SaSsoErrorCode.CODE_30006);
|
||||
}
|
||||
|
||||
// 极端场景下,sso-server 中心的单点注销可能并不会通知到当前 client 端,所以这里需要再补一刀
|
||||
if(stpLogic.isLogin()) {
|
||||
stpLogic.logout(logoutParameter);
|
||||
}
|
||||
return _ssoLogoutBack(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装:校验ticket,取出loginId,如果 ticket 无效则抛出异常 (适用于模式二或模式三)
|
||||
@ -294,70 +301,90 @@ public class SaSsoClientProcessor {
|
||||
*/
|
||||
public SaCheckTicketResult checkTicket(String ticket, String currUri) {
|
||||
SaSsoClientConfig cfg = ssoClientTemplate.getClientConfig();
|
||||
|
||||
// 两种模式:
|
||||
// isHttp=true:模式三,使用 http 请求从认证中心校验ticket
|
||||
// isHttp=false:模式二,直连 redis 中校验 ticket
|
||||
if(cfg.getIsHttp()) {
|
||||
return _checkTicketByHttp(ticket, currUri);
|
||||
} else {
|
||||
return _checkTicketByRedis(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 ticket,http 请求方式
|
||||
* @param ticket /
|
||||
* @param currUri /
|
||||
* @return /
|
||||
*/
|
||||
public SaCheckTicketResult _checkTicketByHttp(String ticket, String currUri) {
|
||||
SaSsoClientConfig cfg = ssoClientTemplate.getClientConfig();
|
||||
ApiName apiName = ssoClientTemplate.apiName;
|
||||
ParamName paramName = ssoClientTemplate.paramName;
|
||||
|
||||
// --------- 两种模式
|
||||
if(cfg.getIsHttp()) {
|
||||
// q1、使用模式三:使用 http 请求从认证中心校验ticket
|
||||
|
||||
// 计算当前 sso-client 的单点注销回调地址
|
||||
String ssoLogoutCall = null;
|
||||
if(cfg.getRegLogoutCall()) {
|
||||
// 如果配置了回调地址,就使用配置的值:
|
||||
if(SaFoxUtil.isNotEmpty(cfg.getCurrSsoLogoutCall())) {
|
||||
ssoLogoutCall = cfg.getCurrSsoLogoutCall();
|
||||
}
|
||||
// 如果提供了当前 uri,则根据此值来计算:
|
||||
else if(SaFoxUtil.isNotEmpty(currUri)) {
|
||||
ssoLogoutCall = SaHolder.getRequest().getUrl().replace(currUri, apiName.ssoLogoutCall);
|
||||
}
|
||||
// 否则视为不注册单点注销回调地址
|
||||
else {
|
||||
}
|
||||
// 计算当前 sso-client 的单点注销回调地址
|
||||
String ssoLogoutCall = null;
|
||||
if(cfg.getRegLogoutCall()) {
|
||||
// 如果配置了回调地址,就使用配置的值:
|
||||
if(SaFoxUtil.isNotEmpty(cfg.getCurrSsoLogoutCall())) {
|
||||
ssoLogoutCall = cfg.getCurrSsoLogoutCall();
|
||||
}
|
||||
|
||||
// 发起请求
|
||||
SaSsoMessage message = ssoClientTemplate.buildCheckTicketMessage(ticket, ssoLogoutCall);
|
||||
SaResult result = ssoClientTemplate.pushMessageAsSaResult(message);
|
||||
|
||||
// 校验
|
||||
if(result.getCode() != null && result.getCode() == SaResult.CODE_SUCCESS) {
|
||||
|
||||
SaCheckTicketResult ctr = new SaCheckTicketResult();
|
||||
ctr.loginId = result.get(paramName.loginId);
|
||||
ctr.tokenValue = result.get(paramName.tokenValue, String.class);
|
||||
ctr.deviceId = result.get(paramName.deviceId, String.class);
|
||||
ctr.remainTokenTimeout = result.get(paramName.remainTokenTimeout, Long.class);
|
||||
ctr.remainSessionTimeout = result.get(paramName.remainSessionTimeout, Long.class);
|
||||
ctr.result = result;
|
||||
|
||||
return ctr;
|
||||
} else {
|
||||
// 将 sso-server 回应的消息作为异常抛出
|
||||
throw new SaSsoException(result.getMsg()).setCode(SaSsoErrorCode.CODE_30005);
|
||||
// 如果提供了当前 uri,则根据此值来计算:
|
||||
else if(SaFoxUtil.isNotEmpty(currUri)) {
|
||||
ssoLogoutCall = SaHolder.getRequest().getUrl().replace(currUri, apiName.ssoLogoutCall);
|
||||
}
|
||||
// 否则视为不注册单点注销回调地址
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
// q2、使用模式二:直连Redis校验ticket
|
||||
// 注意此处调用了 SaSsoServerProcessor 处理器里的方法,
|
||||
// 这意味着如果你的 sso-server 端重写了 SaSsoServerProcessor 里的部分方法,
|
||||
// 而在当前 sso-client 没有按照相应格式重写 SaSsoClientProcessor 里的方法,
|
||||
// 可能会导致调用失败(注意是可能,而非一定),
|
||||
// 解决方案为:在当前 sso-client 端也按照 sso-server 端的格式重写 SaSsoClientProcessor 里的方法
|
||||
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
TicketModel ticketModel = SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(ticket, ssoClientTemplate.getClient());
|
||||
|
||||
SaCheckTicketResult ctr = new SaCheckTicketResult();
|
||||
ctr.loginId = ticketModel.getLoginId();
|
||||
ctr.tokenValue = ticketModel.getTokenValue();
|
||||
ctr.deviceId = stpLogic.getLoginDeviceIdByToken(ticketModel.getTokenValue());
|
||||
ctr.remainTokenTimeout = stpLogic.getTokenTimeout(ticketModel.getTokenValue());
|
||||
ctr.remainSessionTimeout = stpLogic.getSessionTimeoutByLoginId(ticketModel.getLoginId());
|
||||
ctr.result = null;
|
||||
|
||||
return ctr;
|
||||
}
|
||||
|
||||
// 发起请求
|
||||
SaSsoMessage message = ssoClientTemplate.buildCheckTicketMessage(ticket, ssoLogoutCall);
|
||||
SaResult result = ssoClientTemplate.pushMessageAsSaResult(message);
|
||||
|
||||
// 如果 sso-server 响应的状态码非200,代表业务失败,将回应的 msg 字段作为异常抛出
|
||||
if(result.getCode() == null || result.getCode() != SaResult.CODE_SUCCESS) {
|
||||
throw new SaSsoException(result.getMsg()).setCode(SaSsoErrorCode.CODE_30005);
|
||||
}
|
||||
|
||||
// 构建返回结果
|
||||
SaCheckTicketResult ctr = new SaCheckTicketResult();
|
||||
ctr.loginId = result.get(paramName.loginId);
|
||||
ctr.tokenValue = result.get(paramName.tokenValue, String.class);
|
||||
ctr.deviceId = result.get(paramName.deviceId, String.class);
|
||||
ctr.remainTokenTimeout = result.get(paramName.remainTokenTimeout, Long.class);
|
||||
ctr.remainSessionTimeout = result.get(paramName.remainSessionTimeout, Long.class);
|
||||
ctr.result = result;
|
||||
|
||||
return ctr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 ticket,直连 redis 方式
|
||||
* @param ticket /
|
||||
* @return /
|
||||
*/
|
||||
public SaCheckTicketResult _checkTicketByRedis(String ticket) {
|
||||
// 直连 redis 校验 ticket
|
||||
// 注意此处调用了 SaSsoServerProcessor 处理器里的方法,
|
||||
// 这意味着如果你的 sso-server 端重写了 SaSsoServerProcessor 里的部分方法,
|
||||
// 而在当前 sso-client 没有按照相应格式重写 SaSsoClientProcessor 里的方法,
|
||||
// 可能会导致调用失败(注意是可能,而非一定,主要取决于你是否改变了数据读写格式),
|
||||
// 解决方案为:在当前 sso-client 端也按照 sso-server 端的格式重写 SaSsoClientProcessor 里的方法
|
||||
|
||||
StpLogic stpLogic = ssoClientTemplate.getStpLogic();
|
||||
TicketModel ticketModel = SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(ticket, ssoClientTemplate.getClient());
|
||||
|
||||
SaCheckTicketResult ctr = new SaCheckTicketResult();
|
||||
ctr.loginId = ticketModel.getLoginId();
|
||||
ctr.tokenValue = ticketModel.getTokenValue();
|
||||
ctr.deviceId = stpLogic.getLoginDeviceIdByToken(ticketModel.getTokenValue());
|
||||
ctr.remainTokenTimeout = stpLogic.getTokenTimeout(ticketModel.getTokenValue());
|
||||
ctr.remainSessionTimeout = stpLogic.getSessionTimeoutByLoginId(ticketModel.getLoginId());
|
||||
ctr.result = null;
|
||||
|
||||
return ctr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,10 +393,8 @@ public class SaSsoClientProcessor {
|
||||
* @param res SaResponse对象
|
||||
* @return 返回结果
|
||||
*/
|
||||
public Object ssoLogoutBack(SaRequest req, SaResponse res) {
|
||||
public Object _ssoLogoutBack(SaRequest req, SaResponse res) {
|
||||
return SaSsoProcessorHelper.ssoLogoutBack(req, res, ssoClientTemplate.paramName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ package cn.dev33.satoken.sso.processor;
|
||||
|
||||
import cn.dev33.satoken.context.model.SaRequest;
|
||||
import cn.dev33.satoken.context.model.SaResponse;
|
||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||
import cn.dev33.satoken.sso.name.ParamName;
|
||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
|
@ -57,13 +57,13 @@ public class SaSsoServerProcessor {
|
||||
|
||||
/**
|
||||
* 分发 Server 端所有请求
|
||||
*
|
||||
* @return 处理结果
|
||||
*/
|
||||
public Object dister() {
|
||||
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaSsoServerConfig cfg = ssoServerTemplate.getServerConfig();
|
||||
ApiName apiName = ssoServerTemplate.apiName;
|
||||
|
||||
// ------------------ 路由分发 ------------------
|
||||
@ -104,36 +104,44 @@ public class SaSsoServerProcessor {
|
||||
StpLogic stpLogic = ssoServerTemplate.getStpLogic();
|
||||
ParamName paramName = ssoServerTemplate.paramName;
|
||||
|
||||
// ---------- 此处有两种情况分开处理:
|
||||
// ---- 情况1:在SSO认证中心尚未登录,需要先去登录
|
||||
// 两种情况:
|
||||
// 情况1:在 SSO 认证中心尚未登录,需要显示登录视图,去登录
|
||||
// 情况2:在 SSO 认证中心已经登录,需要重定向回 Client 端
|
||||
|
||||
// 情况1,显示登录视图
|
||||
if( ! stpLogic.isLogin()) {
|
||||
return ssoServerTemplate.strategy.notLoginView.get();
|
||||
}
|
||||
// ---- 情况2:在SSO认证中心已经登录,需要重定向回 Client 端,而这又分为两种方式:
|
||||
|
||||
// 情况2,开始跳转
|
||||
String mode = req.getParam(paramName.mode, SaSsoConsts.MODE_TICKET);
|
||||
String redirect = req.getParam(paramName.redirect);
|
||||
String client = req.getParam(paramName.client);
|
||||
|
||||
// 若 redirect 为空,则选择 homeRoute,若 homeRoute 也为空,则抛出异常
|
||||
if(SaFoxUtil.isEmpty(redirect)) {
|
||||
if(SaFoxUtil.isEmpty(cfg.getHomeRoute())) {
|
||||
throw new SaSsoException("未指定 redirect 参数,也未配置 homeRoute 路由,无法完成重定向操作").setCode(SaSsoErrorCode.CODE_30014);
|
||||
}
|
||||
ssoServerTemplate.strategy.jumpToRedirectUrlNotice.run(cfg.getHomeRoute());
|
||||
return res.redirect(cfg.getHomeRoute());
|
||||
}
|
||||
|
||||
// 构建最终重定向地址
|
||||
String redirectUrl = SaSugar.get(() -> {
|
||||
// 方式1:直接重定向回Client端 (mode=simple)
|
||||
|
||||
// 若 redirect 参数为空,说明用户并不是从 client 重定向来的,而是直接访问的 http://sso-server.com/sso/auth 地址
|
||||
// 此时需要跳转到配置的 homeRoute 路由上,
|
||||
// 若 homeRoute 也为空,则没有明确的跳转地址了,需要抛出异常
|
||||
if(SaFoxUtil.isEmpty(redirect)) {
|
||||
if(SaFoxUtil.isEmpty(cfg.getHomeRoute())) {
|
||||
throw new SaSsoException("未指定 redirect 参数,也未配置 homeRoute 路由,无法完成重定向操作").setCode(SaSsoErrorCode.CODE_30014);
|
||||
}
|
||||
return cfg.getHomeRoute();
|
||||
}
|
||||
|
||||
// 方式1:直接重定向回Client端 (mode=simple,一般是模式一)
|
||||
if(mode.equals(SaSsoConsts.MODE_SIMPLE)) {
|
||||
ssoServerTemplate.checkRedirectUrl(client, redirect);
|
||||
return redirect;
|
||||
} else {
|
||||
// 方式2:带着 ticket 参数重定向回Client端 (mode=ticket)
|
||||
// 方式2:带着 ticket 参数重定向回Client端 (mode=ticket,一般是模式二、三)
|
||||
|
||||
// 构建并跳转
|
||||
String _redirectUrl = ssoServerTemplate.buildRedirectUrl(client, redirect, stpLogic.getLoginId(), stpLogic.getTokenValue());
|
||||
// 构建成功,说明 redirect 地址合法,此时需要更新一下该账号的Session有效期
|
||||
|
||||
// 构建成功,说明 redirect 地址合法,此时需要更新一下当前 token 有效期
|
||||
if(cfg.getAutoRenewTimeout()) {
|
||||
stpLogic.renewTimeout(stpLogic.getConfigOrGlobal().getTimeout());
|
||||
}
|
||||
@ -151,13 +159,14 @@ public class SaSsoServerProcessor {
|
||||
* @return 处理结果
|
||||
*/
|
||||
public Object ssoDoLogin() {
|
||||
// 获取对象
|
||||
// 获取参数
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaSsoServerConfig cfg = ssoServerTemplate.getServerConfig();
|
||||
ParamName paramName = ssoServerTemplate.paramName;
|
||||
String name = req.getParam(paramName.name);
|
||||
String pwd = req.getParam(paramName.pwd);
|
||||
|
||||
// 处理
|
||||
return ssoServerTemplate.strategy.doLoginHandle.apply(req.getParam(paramName.name), req.getParam(paramName.pwd));
|
||||
return ssoServerTemplate.strategy.doLoginHandle.apply(name, pwd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,14 +177,15 @@ public class SaSsoServerProcessor {
|
||||
// 获取对象
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
SaResponse res = SaHolder.getResponse();
|
||||
Object loginId = ssoServerTemplate.getStpLogic().getLoginIdDefaultNull();
|
||||
StpLogic stpLogic = ssoServerTemplate.getStpLogic();
|
||||
Object loginId = stpLogic.getLoginIdDefaultNull();
|
||||
boolean singleDeviceIdLogout = req.isParam(ssoServerTemplate.paramName.singleDeviceIdLogout, "true");
|
||||
|
||||
// 单点注销
|
||||
if(SaFoxUtil.isNotEmpty(loginId)) {
|
||||
SaLogoutParameter logoutParameter = ssoServerTemplate.getStpLogic().createSaLogoutParameter();
|
||||
SaLogoutParameter logoutParameter = stpLogic.createSaLogoutParameter();
|
||||
if(singleDeviceIdLogout) {
|
||||
logoutParameter.setDeviceId(ssoServerTemplate.getStpLogic().getLoginDeviceId());
|
||||
logoutParameter.setDeviceId(stpLogic.getLoginDeviceId());
|
||||
}
|
||||
ssoServerTemplate.ssoLogout(loginId, logoutParameter);
|
||||
}
|
||||
@ -202,7 +212,7 @@ public class SaSsoServerProcessor {
|
||||
return SaResult.error("无效 client 标识:" + client);
|
||||
}
|
||||
|
||||
// 3、校验签名
|
||||
// 3、校验参数签名
|
||||
Map<String, String> paramMap = req.getParamMap();
|
||||
if(ssoServerConfig.getIsCheckSign()) {
|
||||
ssoServerTemplate.getSignTemplate(client).checkParamMap(paramMap);
|
||||
@ -210,10 +220,10 @@ public class SaSsoServerProcessor {
|
||||
SaSsoManager.printNoCheckSignWarningByRuntime();
|
||||
}
|
||||
|
||||
// 处理消息
|
||||
// 4、处理消息
|
||||
SaSsoMessage message = new SaSsoMessage(paramMap);
|
||||
if( ! ssoServerTemplate.messageHolder.hasHandle(message.getType())) {
|
||||
return SaResult.error("未能找到消息处理器: " + message.getType());
|
||||
return SaResult.error("未能找到消息处理器:" + message.getType());
|
||||
}
|
||||
return ssoServerTemplate.handleMessage(message);
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.fun.SaParamRetFunction;
|
||||
import cn.dev33.satoken.sso.function.SendHttpFunction;
|
||||
import cn.dev33.satoken.sso.function.TicketResultHandleFunction;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO Client 相关策略
|
||||
@ -62,4 +65,16 @@ public class SaSsoClientStrategy {
|
||||
return loginId;
|
||||
};
|
||||
|
||||
/**
|
||||
* 发送 Http 请求,并将响应结果转换为 SaResult
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @return 返回的结果
|
||||
*/
|
||||
public SaResult requestAsSaResult(String url) {
|
||||
String body = sendHttp.apply(url);
|
||||
Map<String, Object> map = SaManager.getSaJsonTemplate().jsonToMap(body);
|
||||
return new SaResult(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ import cn.dev33.satoken.sso.function.NotLoginViewFunction;
|
||||
import cn.dev33.satoken.sso.function.SendHttpFunction;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO Server 相关策略
|
||||
*
|
||||
@ -66,4 +68,16 @@ public class SaSsoServerStrategy {
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 发送 Http 请求,并将响应结果转换为 SaResult
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @return 返回的结果
|
||||
*/
|
||||
public SaResult requestAsSaResult(String url) {
|
||||
String body = sendHttp.apply(url);
|
||||
Map<String, Object> map = SaManager.getSaJsonTemplate().jsonToMap(body);
|
||||
return new SaResult(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import cn.dev33.satoken.util.SaResult;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 模板方法类 (Client端)
|
||||
* SSO 模板方法类 (Client端)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.38.0
|
||||
@ -50,10 +50,11 @@ public class SaSsoClientTemplate extends SaSsoTemplate {
|
||||
}
|
||||
|
||||
|
||||
// ------------------- SSO 模式三相关 -------------------
|
||||
// ------------------- getData 相关 -------------------
|
||||
|
||||
/**
|
||||
* 根据配置的 getData 地址,查询数据
|
||||
*
|
||||
* @param paramMap 查询参数
|
||||
* @return 查询结果
|
||||
*/
|
||||
@ -64,6 +65,7 @@ public class SaSsoClientTemplate extends SaSsoTemplate {
|
||||
|
||||
/**
|
||||
* 根据自定义 path 地址,查询数据 (此方法需要配置 sa-token.sso.server-url 地址)
|
||||
*
|
||||
* @param path 自定义 path
|
||||
* @param paramMap 查询参数
|
||||
* @return 查询结果
|
||||
@ -73,44 +75,6 @@ public class SaSsoClientTemplate extends SaSsoTemplate {
|
||||
return strategy.sendHttp.apply(url);
|
||||
}
|
||||
|
||||
// ---------------------- 构建URL ----------------------
|
||||
|
||||
/**
|
||||
* 构建URL:Server端 单点登录地址
|
||||
* @param clientLoginUrl Client端登录地址
|
||||
* @param back 回调路径
|
||||
* @return [SSO-Server端-认证地址 ]
|
||||
*/
|
||||
public String buildServerAuthUrl(String clientLoginUrl, String back) {
|
||||
SaSsoClientConfig ssoConfig = getClientConfig();
|
||||
|
||||
// 服务端认证地址
|
||||
String serverUrl = ssoConfig.splicingAuthUrl();
|
||||
|
||||
// 拼接客户端标识
|
||||
String client = getClient();
|
||||
if(SaFoxUtil.isNotEmpty(client)) {
|
||||
serverUrl = SaFoxUtil.joinParam(serverUrl, paramName.client, client);
|
||||
}
|
||||
|
||||
// 对back地址编码
|
||||
back = (back == null ? "" : back);
|
||||
back = SaFoxUtil.encodeUrl(back);
|
||||
|
||||
// 开始拼接 sso 统一认证地址,形如:serverAuthUrl = http://xxx.com?redirectUrl=xxx.com?back=xxx.com
|
||||
|
||||
/*
|
||||
* 部分 Servlet 版本 request.getRequestURL() 返回的 url 带有 query 参数,形如:http://domain.com?id=1,
|
||||
* 如果不加判断会造成最终生成的 serverAuthUrl 带有双 back 参数 ,这个 if 判断正是为了解决此问题
|
||||
*/
|
||||
if( ! clientLoginUrl.contains(paramName.back + "=") ) {
|
||||
clientLoginUrl = SaFoxUtil.joinParam(clientLoginUrl, paramName.back, back);
|
||||
}
|
||||
|
||||
// 返回
|
||||
return SaFoxUtil.joinParam(serverUrl, paramName.redirect, clientLoginUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建URL:Server端 getData 地址,带签名等参数
|
||||
* @param paramMap 查询参数
|
||||
@ -146,55 +110,49 @@ public class SaSsoClientTemplate extends SaSsoTemplate {
|
||||
return SaFoxUtil.joinParam(url, signParamsStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建消息:校验 ticket
|
||||
*
|
||||
* @param ticket ticket码
|
||||
* @param ssoLogoutCallUrl 单点注销时的回调URL
|
||||
* @return 构建完毕的URL
|
||||
*/
|
||||
public SaSsoMessage buildCheckTicketMessage(String ticket, String ssoLogoutCallUrl) {
|
||||
SaSsoClientConfig ssoConfig = getClientConfig();
|
||||
SaSsoMessage message = new SaSsoMessage();
|
||||
message.setType(SaSsoConsts.MESSAGE_CHECK_TICKET);
|
||||
message.set(paramName.client, getClient());
|
||||
message.set(paramName.ticket, ticket);
|
||||
message.set(paramName.ssoLogoutCall, ssoLogoutCallUrl);
|
||||
return message;
|
||||
}
|
||||
|
||||
// ---------------------- 构建交互地址 ----------------------
|
||||
|
||||
/**
|
||||
* 构建消息:单点注销
|
||||
*
|
||||
* @param loginId 要注销的账号 id
|
||||
* @param logoutParameter 单点注销
|
||||
* @return 单点注销URL
|
||||
* 构建URL:Server端 单点登录授权地址,
|
||||
* <br/> 形如:http://sso-server.com/sso/auth?redirectUrl=http://sso-client.com/sso/login?back=http://sso-client.com
|
||||
* @param clientLoginUrl Client端登录地址
|
||||
* @param back 回调路径
|
||||
* @return [SSO-Server端-认证地址 ]
|
||||
*/
|
||||
public SaSsoMessage buildSloMessage(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
public String buildServerAuthUrl(String clientLoginUrl, String back) {
|
||||
SaSsoClientConfig ssoConfig = getClientConfig();
|
||||
SaSsoMessage message = new SaSsoMessage();
|
||||
message.setType(SaSsoConsts.MESSAGE_SIGNOUT);
|
||||
message.set(paramName.client, getClient());
|
||||
message.set(paramName.loginId, loginId);
|
||||
message.set(paramName.deviceId, logoutParameter.getDeviceId());
|
||||
return message;
|
||||
|
||||
// 服务端认证地址
|
||||
String serverUrl = ssoConfig.splicingAuthUrl();
|
||||
|
||||
// 拼接客户端标识
|
||||
String client = getClient();
|
||||
if(SaFoxUtil.isNotEmpty(client)) {
|
||||
serverUrl = SaFoxUtil.joinParam(serverUrl, paramName.client, client);
|
||||
}
|
||||
|
||||
// 对back地址编码
|
||||
back = (back == null ? "" : back);
|
||||
back = SaFoxUtil.encodeUrl(back);
|
||||
|
||||
// 开始拼接 sso 统一认证地址,形如:serverAuthUrl = http://xxx.com?redirectUrl=xxx.com?back=xxx.com
|
||||
|
||||
/*
|
||||
* 部分 Servlet 版本 request.getRequestURL() 返回的 url 带有 query 参数,形如:http://domain.com?id=1,
|
||||
* 如果不加判断会造成最终生成的 serverAuthUrl 带有双 back 参数 ,这个 if 判断正是为了解决此问题
|
||||
*/
|
||||
if( ! clientLoginUrl.contains(paramName.back + "=") ) {
|
||||
clientLoginUrl = SaFoxUtil.joinParam(clientLoginUrl, paramName.back, back);
|
||||
}
|
||||
|
||||
// 返回
|
||||
return SaFoxUtil.joinParam(serverUrl, paramName.redirect, clientLoginUrl);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 消息推送 -------------------
|
||||
|
||||
/**
|
||||
* 发送 Http 请求,并将响应结果转换为 SaResult
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @return 返回的结果
|
||||
*/
|
||||
public SaResult requestAsSaResult(String url) {
|
||||
String body = strategy.sendHttp.apply(url);
|
||||
Map<String, Object> map = SaManager.getSaJsonTemplate().jsonToMap(body);
|
||||
return new SaResult(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向 sso-server 推送消息
|
||||
*
|
||||
@ -230,6 +188,40 @@ public class SaSsoClientTemplate extends SaSsoTemplate {
|
||||
return new SaResult(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建消息:校验 ticket
|
||||
*
|
||||
* @param ticket ticket码
|
||||
* @param ssoLogoutCallUrl 单点注销时的回调URL
|
||||
* @return 构建完毕的URL
|
||||
*/
|
||||
public SaSsoMessage buildCheckTicketMessage(String ticket, String ssoLogoutCallUrl) {
|
||||
SaSsoClientConfig ssoConfig = getClientConfig();
|
||||
SaSsoMessage message = new SaSsoMessage();
|
||||
message.setType(SaSsoConsts.MESSAGE_CHECK_TICKET);
|
||||
message.set(paramName.client, getClient());
|
||||
message.set(paramName.ticket, ticket);
|
||||
message.set(paramName.ssoLogoutCall, ssoLogoutCallUrl);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建消息:单点注销
|
||||
*
|
||||
* @param loginId 要注销的账号 id
|
||||
* @param logoutParameter 单点注销
|
||||
* @return 单点注销URL
|
||||
*/
|
||||
public SaSsoMessage buildSloMessage(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
SaSsoClientConfig ssoConfig = getClientConfig();
|
||||
SaSsoMessage message = new SaSsoMessage();
|
||||
message.setType(SaSsoConsts.MESSAGE_SIGNOUT);
|
||||
message.set(paramName.client, getClient());
|
||||
message.set(paramName.loginId, loginId);
|
||||
message.set(paramName.deviceId, logoutParameter.getDeviceId());
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
// ------------------- Bean 对象获取 -------------------
|
||||
|
||||
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.sso.template;
|
||||
|
||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
|
||||
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* SSO 模板方法类 (Client端)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.38.0
|
||||
*/
|
||||
public class SaSsoClientUtil extends SaSsoTemplate {
|
||||
|
||||
private SaSsoClientUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回底层使用的 SaSsoClientTemplate 对象
|
||||
* @return /
|
||||
*/
|
||||
public static SaSsoClientTemplate getSsoTemplate() {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate;
|
||||
}
|
||||
|
||||
|
||||
// ------------------- getData 相关 -------------------
|
||||
|
||||
/**
|
||||
* 根据配置的 getData 地址,查询数据
|
||||
*
|
||||
* @param paramMap 查询参数
|
||||
* @return 查询结果
|
||||
*/
|
||||
public static Object getData(Map<String, Object> paramMap) {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate.getData(paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据自定义 path 地址,查询数据 (此方法需要配置 sa-token.sso.server-url 地址)
|
||||
*
|
||||
* @param path 自定义 path
|
||||
* @param paramMap 查询参数
|
||||
* @return 查询结果
|
||||
*/
|
||||
public static Object getData(String path, Map<String, Object> paramMap) {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate.getData(path, paramMap);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- 构建交互地址 ----------------------
|
||||
|
||||
/**
|
||||
* 构建URL:Server端 单点登录授权地址,
|
||||
* <br/> 形如:http://sso-server.com/sso/auth?redirectUrl=http://sso-client.com/sso/login?back=http://sso-client.com
|
||||
* @param clientLoginUrl Client端登录地址
|
||||
* @param back 回调路径
|
||||
* @return [SSO-Server端-认证地址 ]
|
||||
*/
|
||||
public static String buildServerAuthUrl(String clientLoginUrl, String back) {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate.buildServerAuthUrl(clientLoginUrl, back);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 消息推送 -------------------
|
||||
|
||||
/**
|
||||
* 向 sso-server 推送消息
|
||||
*
|
||||
* @param message /
|
||||
* @return /
|
||||
*/
|
||||
public static String pushMessage(SaSsoMessage message) {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate.pushMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向 sso-server 推送消息,并将返回值转为 SaResult
|
||||
*
|
||||
* @param message /
|
||||
* @return /
|
||||
*/
|
||||
public static SaResult pushMessageAsSaResult(SaSsoMessage message) {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate.pushMessageAsSaResult(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建消息:校验 ticket
|
||||
*
|
||||
* @param ticket ticket码
|
||||
* @param ssoLogoutCallUrl 单点注销时的回调URL
|
||||
* @return 构建完毕的URL
|
||||
*/
|
||||
public static SaSsoMessage buildCheckTicketMessage(String ticket, String ssoLogoutCallUrl) {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate.buildCheckTicketMessage(ticket, ssoLogoutCallUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建消息:单点注销
|
||||
*
|
||||
* @param loginId 要注销的账号 id
|
||||
* @param logoutParameter 单点注销
|
||||
* @return 单点注销URL
|
||||
*/
|
||||
public static SaSsoMessage buildSloMessage(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
return SaSsoClientProcessor.instance.ssoClientTemplate.buildSloMessage(loginId, logoutParameter);
|
||||
}
|
||||
|
||||
}
|
@ -39,7 +39,7 @@ import cn.dev33.satoken.util.SaResult;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 模板方法类 (Server端)
|
||||
* SSO 模板方法类 (Server端)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.38.0
|
||||
@ -58,40 +58,17 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
|
||||
// ---------------------- Ticket 操作 ----------------------
|
||||
|
||||
// 增删改
|
||||
|
||||
/**
|
||||
* 保存 Ticket
|
||||
* @param ticketModel /
|
||||
*/
|
||||
public void saveTicket(TicketModel ticketModel) {
|
||||
long ticketTimeout = getServerConfig().getTicketTimeout();
|
||||
SaManager.getSaTokenDao().setObject(splicingTicketSaveKey(ticketModel.getTicket()), ticketModel, ticketTimeout);
|
||||
SaManager.getSaTokenDao().setObject(splicingTicketModelSaveKey(ticketModel.getTicket()), ticketModel, ticketTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存 Ticket 索引 (id 反查 ticket)
|
||||
*
|
||||
* @param client 应用端
|
||||
* @param ticket ticket码
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void saveTicketIndex(String client, Object loginId, String ticket) {
|
||||
long ticketTimeout = getServerConfig().getTicketTimeout();
|
||||
SaManager.getSaTokenDao().set(splicingTicketIndexKey(client, loginId), String.valueOf(ticket), ticketTimeout);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 保存 Ticket 关联的 client
|
||||
// * @param ticket ticket码
|
||||
// * @param client 客户端标识
|
||||
// */
|
||||
// public void saveTicketToClient(String ticket, String client) {
|
||||
// if(SaFoxUtil.isEmpty(client)) {
|
||||
// return;
|
||||
// }
|
||||
// long ticketTimeout = getServerConfig().getTicketTimeout();
|
||||
// SaManager.getSaTokenDao().set(splicingTicketToClientSaveKey(ticket), client, ticketTimeout);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 删除 Ticket
|
||||
* @param ticket Ticket码
|
||||
@ -100,36 +77,59 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
if(ticket == null) {
|
||||
return;
|
||||
}
|
||||
SaManager.getSaTokenDao().deleteObject(splicingTicketSaveKey(ticket));
|
||||
SaManager.getSaTokenDao().deleteObject(splicingTicketModelSaveKey(ticket));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Ticket索引
|
||||
* 根据参数创建一个 ticket 码
|
||||
*
|
||||
* @param client 应用标识
|
||||
* @param loginId 账号id
|
||||
* @param client 客户端标识
|
||||
* @param loginId 账号 id
|
||||
* @param tokenValue 会话 Token
|
||||
* @return Ticket码
|
||||
*/
|
||||
public void deleteTicketIndex(String client, Object loginId) {
|
||||
if(loginId == null) {
|
||||
return;
|
||||
}
|
||||
SaManager.getSaTokenDao().delete(splicingTicketIndexKey(client, loginId));
|
||||
public TicketModel createTicket(String client, Object loginId, String tokenValue) {
|
||||
TicketModel ticketModel = new TicketModel();
|
||||
ticketModel.setTicket(randomTicket(loginId));
|
||||
ticketModel.setClient(client);
|
||||
ticketModel.setLoginId(loginId);
|
||||
ticketModel.setTokenValue(tokenValue);
|
||||
return ticketModel;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 删除 Ticket 关联的 client
|
||||
// *
|
||||
// * @param ticket Ticket码
|
||||
// */
|
||||
// public void deleteTicketToClient(String ticket) {
|
||||
// if(ticket == null) {
|
||||
// return;
|
||||
// }
|
||||
// SaManager.getSaTokenDao().delete(splicingTicketToClientSaveKey(ticket));
|
||||
// }
|
||||
/**
|
||||
* 根据参数创建一个 ticket 码,并保存
|
||||
*
|
||||
* @param client 客户端标识
|
||||
* @param loginId 账号 id
|
||||
* @param tokenValue 会话 Token
|
||||
* @return Ticket码
|
||||
*/
|
||||
public String createTicketAndSave(String client, Object loginId, String tokenValue) {
|
||||
// 创建
|
||||
TicketModel ticketModel = createTicket(client, loginId, tokenValue);
|
||||
|
||||
// 保存
|
||||
saveTicket(ticketModel);
|
||||
saveTicketIndex(client, loginId, ticketModel.getTicket());
|
||||
|
||||
// 返回
|
||||
return ticketModel.getTicket();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 ticket ,如果 ticket 码无效则返回 null
|
||||
* 随机一个 Ticket 码
|
||||
* @param loginId 账号id
|
||||
* @return Ticket 码
|
||||
*/
|
||||
public String randomTicket(Object loginId) {
|
||||
return SaFoxUtil.getRandomString(64);
|
||||
}
|
||||
|
||||
// 查
|
||||
|
||||
/**
|
||||
* 查询 ticket ,如果 ticket 无效则返回 null
|
||||
*
|
||||
* @param ticket Ticket码
|
||||
* @return 账号id
|
||||
@ -138,7 +138,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
if(SaFoxUtil.isEmpty(ticket)) {
|
||||
return null;
|
||||
}
|
||||
return SaManager.getSaTokenDao().getObject(splicingTicketSaveKey(ticket), TicketModel.class);
|
||||
return SaManager.getSaTokenDao().getObject(splicingTicketModelSaveKey(ticket), TicketModel.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,57 +165,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
return SaFoxUtil.getValueByType(getLoginId(ticket), cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 指定 client、loginId 其所属的 ticket 值
|
||||
*
|
||||
* @param client 应用
|
||||
* @param loginId 账号id
|
||||
* @return Ticket值
|
||||
*/
|
||||
public String getTicketValue(String client, Object loginId) {
|
||||
if(loginId == null) {
|
||||
return null;
|
||||
}
|
||||
return SaManager.getSaTokenDao().get(splicingTicketIndexKey(client, loginId));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 查询 ticket 关联的 client,如果 ticket 码无效则返回 null
|
||||
// * @param ticket Ticket码
|
||||
// * @return 账号id
|
||||
// */
|
||||
// public String getTicketToClient(String ticket) {
|
||||
// if(SaFoxUtil.isEmpty(ticket)) {
|
||||
// return null;
|
||||
// }
|
||||
// return SaManager.getSaTokenDao().get(splicingTicketToClientSaveKey(ticket));
|
||||
// }
|
||||
|
||||
//
|
||||
/**
|
||||
* 根据参数创建一个 ticket 码
|
||||
*
|
||||
* @param client 客户端标识
|
||||
* @param loginId 账号 id
|
||||
* @param tokenValue 会话 Token
|
||||
* @return Ticket码
|
||||
*/
|
||||
public String createTicket(String client, Object loginId, String tokenValue) {
|
||||
// 创建 Ticket
|
||||
String ticket = randomTicket(loginId);
|
||||
TicketModel ticketModel = new TicketModel();
|
||||
ticketModel.setTicket(ticket);
|
||||
ticketModel.setClient(client);
|
||||
ticketModel.setLoginId(loginId);
|
||||
ticketModel.setTokenValue(tokenValue);
|
||||
|
||||
// 保存 Ticket
|
||||
saveTicket(ticketModel);
|
||||
saveTicketIndex(client, loginId, ticket);
|
||||
|
||||
// 返回 Ticket
|
||||
return ticket;
|
||||
}
|
||||
// 校验
|
||||
|
||||
/**
|
||||
* 校验 Ticket,无效 ticket 会抛出异常
|
||||
@ -271,13 +221,45 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
return ticketModel;
|
||||
}
|
||||
|
||||
// ticket 索引
|
||||
|
||||
/**
|
||||
* 随机一个 Ticket码
|
||||
* 保存 Ticket 索引 (id 反查 ticket)
|
||||
*
|
||||
* @param client 应用端
|
||||
* @param ticket ticket码
|
||||
* @param loginId 账号id
|
||||
* @return Ticket码
|
||||
*/
|
||||
public String randomTicket(Object loginId) {
|
||||
return SaFoxUtil.getRandomString(64);
|
||||
public void saveTicketIndex(String client, Object loginId, String ticket) {
|
||||
long ticketTimeout = getServerConfig().getTicketTimeout();
|
||||
SaManager.getSaTokenDao().set(splicingTicketIndexKey(client, loginId), String.valueOf(ticket), ticketTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Ticket 索引
|
||||
*
|
||||
* @param client 应用标识
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void deleteTicketIndex(String client, Object loginId) {
|
||||
if(loginId == null) {
|
||||
return;
|
||||
}
|
||||
SaManager.getSaTokenDao().delete(splicingTicketIndexKey(client, loginId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 指定 client、loginId 其所属的 ticket 值
|
||||
*
|
||||
* @param client 应用
|
||||
* @param loginId 账号id
|
||||
* @return Ticket值
|
||||
*/
|
||||
public String getTicketValue(String client, Object loginId) {
|
||||
if(loginId == null) {
|
||||
return null;
|
||||
}
|
||||
return SaManager.getSaTokenDao().get(splicingTicketIndexKey(client, loginId));
|
||||
}
|
||||
|
||||
|
||||
@ -289,8 +271,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
* @return /
|
||||
*/
|
||||
public List<SaSsoClientModel> getClients() {
|
||||
Map<String, SaSsoClientModel> clients = getServerConfig().getClients();
|
||||
return new ArrayList<>(clients.values());
|
||||
return new ArrayList<>(getServerConfig().getClients().values());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,7 +332,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
List<SaSsoClientModel> list = new ArrayList<>();
|
||||
List<SaSsoClientModel> clients = getClients();
|
||||
for(SaSsoClientModel scm : clients) {
|
||||
if (scm.isValidNoticeUrl()) {
|
||||
if (scm.getIsPush()) {
|
||||
list.add(scm);
|
||||
}
|
||||
}
|
||||
@ -379,14 +360,15 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
deleteTicket(getTicketValue(client, loginId));
|
||||
|
||||
// 创建 新Ticket
|
||||
String ticket = createTicket(client, loginId, tokenValue);
|
||||
String ticket = createTicketAndSave(client, loginId, tokenValue);
|
||||
|
||||
// 构建 授权重定向地址 (Server端 根据此地址向 Client端 下放Ticket)
|
||||
// 构建 授权重定向地址 (Server端 根据此地址向 Client端 下放 Ticket)
|
||||
return SaFoxUtil.joinParam(encodeBackParam(redirect), paramName.ticket, ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对url中的back参数进行URL编码, 解决超链接重定向后参数丢失的bug
|
||||
* 对 url 中的 back 参数进行 URL 编码, 解决超链接重定向后参数丢失的 bug
|
||||
*
|
||||
* @param url url
|
||||
* @return 编码过后的url
|
||||
*/
|
||||
@ -412,7 +394,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验重定向url合法性
|
||||
* 校验重定向 url 合法性
|
||||
*
|
||||
* @param client 应用标识
|
||||
* @param url 下放ticket的url地址
|
||||
@ -513,7 +495,8 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
// ------------------- 单点注销 -------------------
|
||||
|
||||
/**
|
||||
* 为指定账号 id 注册单点注销回调信息(模式三)
|
||||
* 为指定账号 id 注册应用接入信息(模式三)
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param client 指定客户端标识,可为null
|
||||
* @param sloCallbackUrl 单点注销时的回调URL
|
||||
@ -539,7 +522,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
for (;;) {
|
||||
if(scmList.size() > maxRegClient) {
|
||||
SaSsoClientInfo removeScm = scmList.remove(0);
|
||||
notifyClientLogout(loginId, null, removeScm, true);
|
||||
notifyClientLogout(loginId, null, removeScm, true, true);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -591,7 +574,6 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
public void ssoLogout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
|
||||
// 1、消息推送:单点注销
|
||||
// TODO 需要把对应的 SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_ 记录也删掉
|
||||
pushToAllClientByLogoutCall(loginId, logoutParameter);
|
||||
|
||||
// 2、SaSession 挂载的 Client 端注销会话
|
||||
@ -601,7 +583,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
}
|
||||
List<SaSsoClientInfo> scmList = session.get(SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_, ArrayList::new);
|
||||
scmList.forEach(scm -> {
|
||||
notifyClientLogout(loginId, logoutParameter.getDeviceId(), scm, false);
|
||||
notifyClientLogout(loginId, logoutParameter.getDeviceId(), scm, false, false);
|
||||
});
|
||||
|
||||
// 3、Server 端本身注销
|
||||
@ -614,17 +596,22 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
* @param deviceId 指定设备 id
|
||||
* @param scm 客户端信息对象
|
||||
* @param autoLogout 是否为超过 maxRegClient 的自动注销
|
||||
* @param isPushWork 如果该 client 没有注册注销回调地址,是否使用 push 消息的方式进行注销回调通知
|
||||
*/
|
||||
public void notifyClientLogout(Object loginId, String deviceId, SaSsoClientInfo scm, boolean autoLogout) {
|
||||
public void notifyClientLogout(Object loginId, String deviceId, SaSsoClientInfo scm, boolean autoLogout, boolean isPushWork) {
|
||||
|
||||
// 如果给个null值,不进行任何操作
|
||||
if(scm == null || scm.mode != SaSsoConsts.SSO_MODE_3) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果此 Client 并没有注册 单点登录 回调地址,则立即返回
|
||||
// 如果此 Client 并没有注册 单点注销 回调地址
|
||||
String sloCallUrl = scm.getSloCallbackUrl();
|
||||
if(SaFoxUtil.isEmpty(sloCallUrl)) {
|
||||
// TODO 代码有效性待验证
|
||||
if(isPushWork && SaFoxUtil.isNotEmpty(scm.getClient())) {
|
||||
pushToClientByLogoutCall(getClient(scm.getClient()), loginId, getStpLogic().createSaLogoutParameter());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -646,18 +633,6 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
|
||||
// ------------------- 消息推送 -------------------
|
||||
|
||||
/**
|
||||
* 发送 Http 请求,并将响应结果转换为 SaResult
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @return 返回的结果
|
||||
*/
|
||||
public SaResult requestAsSaResult(String url) {
|
||||
String body = strategy.sendHttp.apply(url);;
|
||||
Map<String, Object> map = SaManager.getSaJsonTemplate().jsonToMap(body);
|
||||
return new SaResult(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定 Client 推送消息
|
||||
* @param clientModel /
|
||||
@ -666,7 +641,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
*/
|
||||
public String pushMessage(SaSsoClientModel clientModel, SaSsoMessage message) {
|
||||
message.checkType();
|
||||
String noticeUrl = clientModel.splicingNoticeUrl();
|
||||
String noticeUrl = clientModel.splicingPushUrl();
|
||||
String paramsStr = getSignTemplate(clientModel.getClient()).addSignParamsAndJoin(message);
|
||||
String finalUrl = SaFoxUtil.joinParam(noticeUrl, paramsStr);
|
||||
return strategy.sendHttp.apply(finalUrl);
|
||||
@ -714,8 +689,8 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
* @param message /
|
||||
*/
|
||||
public void pushToAllClient(SaSsoMessage message) {
|
||||
List<SaSsoClientModel> mode3Clients = getNeedPushClients();
|
||||
for (SaSsoClientModel client : mode3Clients) {
|
||||
List<SaSsoClientModel> needPushClients = getNeedPushClients();
|
||||
for (SaSsoClientModel client : needPushClients) {
|
||||
pushMessage(client, message);
|
||||
}
|
||||
}
|
||||
@ -730,15 +705,25 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
List<SaSsoClientModel> npClients = getNeedPushClients();
|
||||
for (SaSsoClientModel client : npClients) {
|
||||
if(client.getIsSlo()) {
|
||||
SaSsoMessage message = new SaSsoMessage();
|
||||
message.setType(SaSsoConsts.MESSAGE_LOGOUT_CALL);
|
||||
message.set(paramName.loginId, loginId);
|
||||
message.set(paramName.deviceId, logoutParameter.getDeviceId());
|
||||
pushMessage(client, message);
|
||||
pushToClientByLogoutCall(client, loginId, logoutParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定 Client 推送消息:单点注销回调
|
||||
*
|
||||
* @param loginId /
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void pushToClientByLogoutCall(SaSsoClientModel client, Object loginId, SaLogoutParameter logoutParameter) {
|
||||
SaSsoMessage message = new SaSsoMessage();
|
||||
message.setType(SaSsoConsts.MESSAGE_LOGOUT_CALL);
|
||||
message.set(paramName.loginId, loginId);
|
||||
message.set(paramName.deviceId, logoutParameter.getDeviceId());
|
||||
pushMessage(client, message);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- Bean 获取 -------------------
|
||||
|
||||
@ -776,25 +761,16 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
// ------------------- 返回相应key -------------------
|
||||
|
||||
/**
|
||||
* 拼接key:Ticket 查 账号Id
|
||||
* 拼接key:TicketModel
|
||||
* @param ticket ticket值
|
||||
* @return key
|
||||
*/
|
||||
public String splicingTicketSaveKey(String ticket) {
|
||||
public String splicingTicketModelSaveKey(String ticket) {
|
||||
return getStpLogic().getConfigOrGlobal().getTokenName() + ":ticket:" + ticket;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 拼接key:Ticket 查 所属的 client
|
||||
// * @param ticket ticket值
|
||||
// * @return key
|
||||
// */
|
||||
// public String splicingTicketToClientSaveKey(String ticket) {
|
||||
// return getStpLogic().getConfigOrGlobal().getTokenName() + ":ticket-client:" + ticket;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 拼接key:账号Id 反查 Ticket
|
||||
* 拼接key:Ticket 索引
|
||||
*
|
||||
* @param client 应用标识
|
||||
* @param id 账号id
|
||||
@ -804,7 +780,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
if(SaFoxUtil.isEmpty(client) || SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
||||
client = SaSsoConsts.CLIENT_ANON;
|
||||
}
|
||||
return getStpLogic().getConfigOrGlobal().getTokenName() + ":id-ticket:" + client + ":" + id;
|
||||
return getStpLogic().getConfigOrGlobal().getTokenName() + ":ticket-index:" + client + ":" + id;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.sso.template;
|
||||
|
||||
import cn.dev33.satoken.sso.config.SaSsoClientModel;
|
||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||
import cn.dev33.satoken.sso.model.TicketModel;
|
||||
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
|
||||
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SSO 工具类 (Server端)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public class SaSsoServerUtil extends SaSsoTemplate {
|
||||
|
||||
private SaSsoServerUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回底层使用的 SaSsoServerTemplate 对象
|
||||
* @return /
|
||||
*/
|
||||
public static SaSsoServerTemplate getSsoTemplate() {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- Ticket 操作 ----------------------
|
||||
|
||||
// 增删改
|
||||
|
||||
/**
|
||||
* 删除 Ticket
|
||||
* @param ticket Ticket码
|
||||
*/
|
||||
public static void deleteTicket(String ticket) {
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate.deleteTicket(ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据参数创建一个 ticket 码,并保存
|
||||
*
|
||||
* @param client 客户端标识
|
||||
* @param loginId 账号 id
|
||||
* @param tokenValue 会话 Token
|
||||
* @return Ticket码
|
||||
*/
|
||||
public static String createTicketAndSave(String client, Object loginId, String tokenValue) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.createTicketAndSave(client, loginId, tokenValue);
|
||||
}
|
||||
|
||||
// 查
|
||||
|
||||
/**
|
||||
* 查询 ticket ,如果 ticket 无效则返回 null
|
||||
*
|
||||
* @param ticket Ticket码
|
||||
* @return 账号id
|
||||
*/
|
||||
public static TicketModel getTicket(String ticket) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getTicket(ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 ticket 指向的 loginId,如果 ticket 码无效则返回 null
|
||||
* @param ticket Ticket码
|
||||
* @return 账号id
|
||||
*/
|
||||
public static Object getLoginId(String ticket) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getLoginId(ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 ticket 指向的 loginId,并转换为指定类型
|
||||
* @param <T> 要转换的类型
|
||||
* @param ticket Ticket码
|
||||
* @param cs 要转换的类型
|
||||
* @return 账号id
|
||||
*/
|
||||
public static <T> T getLoginId(String ticket, Class<T> cs) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getLoginId(ticket, cs);
|
||||
}
|
||||
|
||||
// 校验
|
||||
|
||||
/**
|
||||
* 校验 Ticket,无效 ticket 会抛出异常
|
||||
*
|
||||
* @param ticket Ticket码
|
||||
* @return /
|
||||
*/
|
||||
public static TicketModel checkTicket(String ticket) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.checkTicket(ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 Ticket 码,无效 ticket 会抛出异常,如果此ticket是有效的,则立即删除
|
||||
* @param ticket Ticket码
|
||||
* @return 账号id
|
||||
*/
|
||||
public static TicketModel checkTicketParamAndDelete(String ticket) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 Ticket,无效 ticket 会抛出异常,如果此ticket是有效的,则立即删除
|
||||
*
|
||||
* @param ticket Ticket码
|
||||
* @param client client 标识
|
||||
* @return /
|
||||
*/
|
||||
public static TicketModel checkTicketParamAndDelete(String ticket, String client) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(ticket, client);
|
||||
}
|
||||
|
||||
// ticket 索引
|
||||
|
||||
/**
|
||||
* 查询 指定 client、loginId 其所属的 ticket 值
|
||||
*
|
||||
* @param client 应用
|
||||
* @param loginId 账号id
|
||||
* @return Ticket值
|
||||
*/
|
||||
public static String getTicketValue(String client, Object loginId) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getTicketValue(client, loginId);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- Client 信息获取 ----------------------
|
||||
|
||||
/**
|
||||
* 获取所有 Client
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static List<SaSsoClientModel> getClients() {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getClients();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用信息,无效 client 返回 null
|
||||
*
|
||||
* @param client /
|
||||
* @return /
|
||||
*/
|
||||
public static SaSsoClientModel getClient(String client) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getClient(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用信息,无效 client 则抛出异常
|
||||
*
|
||||
* @param client /
|
||||
* @return /
|
||||
*/
|
||||
public static SaSsoClientModel getClientNotNull(String client) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getClientNotNull(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取匿名 client 信息
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static SaSsoClientModel getAnonClient() {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getAnonClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有需要接收消息推送的 Client
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static List<SaSsoClientModel> getNeedPushClients() {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.getNeedPushClients();
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 重定向 URL 构建与校验 -------------------
|
||||
|
||||
/**
|
||||
* 构建 URL:sso-server 端向 sso-client 下放 ticket 的地址
|
||||
*
|
||||
* @param client 客户端标识
|
||||
* @param redirect sso-client 端的重定向地址
|
||||
* @param loginId 账号 id
|
||||
* @param tokenValue 会话 token
|
||||
* @return /
|
||||
*/
|
||||
public static String buildRedirectUrl(String client, String redirect, Object loginId, String tokenValue) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.buildRedirectUrl(client, redirect, loginId, tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验重定向 url 合法性
|
||||
*
|
||||
* @param client 应用标识
|
||||
* @param url 下放ticket的url地址
|
||||
*/
|
||||
public static void checkRedirectUrl(String client, String url) {
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate.checkRedirectUrl(client, url);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 单点注销 -------------------
|
||||
|
||||
/**
|
||||
* 指定账号单点注销
|
||||
*
|
||||
* @param loginId 指定账号
|
||||
*/
|
||||
public static void ssoLogout(Object loginId) {
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate.ssoLogout(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定账号单点注销
|
||||
*
|
||||
* @param loginId 指定账号
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public static void ssoLogout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate.ssoLogout(loginId, logoutParameter);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 消息推送 -------------------
|
||||
|
||||
/**
|
||||
* 向指定 Client 推送消息
|
||||
* @param clientModel /
|
||||
* @param message /
|
||||
* @return /
|
||||
*/
|
||||
public static String pushMessage(SaSsoClientModel clientModel, SaSsoMessage message) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.pushMessage(clientModel, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定 client 推送消息,并将返回值转为 SaResult
|
||||
*
|
||||
* @param clientModel /
|
||||
* @param message /
|
||||
* @return /
|
||||
*/
|
||||
public static SaResult pushMessageAsSaResult(SaSsoClientModel clientModel, SaSsoMessage message) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.pushMessageAsSaResult(clientModel, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定 Client 推送消息
|
||||
* @param client /
|
||||
* @param message /
|
||||
* @return /
|
||||
*/
|
||||
public static String pushMessage(String client, SaSsoMessage message) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.pushMessage(client, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定 client 推送消息,并将返回值转为 SaResult
|
||||
*
|
||||
* @param client /
|
||||
* @param message /
|
||||
* @return /
|
||||
*/
|
||||
public static SaResult pushMessageAsSaResult(String client, SaSsoMessage message) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.pushMessageAsSaResult(client, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向所有 Client 推送消息
|
||||
*
|
||||
* @param message /
|
||||
*/
|
||||
public static void pushToAllClient(SaSsoMessage message) {
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate.pushToAllClient(message);
|
||||
}
|
||||
|
||||
}
|
@ -15,19 +15,15 @@
|
||||
*/
|
||||
package cn.dev33.satoken.sso.template;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||
import cn.dev33.satoken.sso.message.SaSsoMessageHolder;
|
||||
import cn.dev33.satoken.sso.name.ApiName;
|
||||
import cn.dev33.satoken.sso.name.ParamName;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token SSO 模板方法类 (公共端)
|
||||
* SSO 模板方法类 (公共端)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.30.0
|
||||
@ -74,18 +70,11 @@ public class SaSsoTemplate {
|
||||
|
||||
// ----------- 消息处理
|
||||
|
||||
/**
|
||||
* SSO 消息处理器 - 持有器
|
||||
*/
|
||||
public SaSsoMessageHolder messageHolder = new SaSsoMessageHolder();
|
||||
|
||||
// /**
|
||||
// * 发送 Http 请求
|
||||
// *
|
||||
// * @param url /
|
||||
// * @return /
|
||||
// */
|
||||
// public String request(String url) {
|
||||
// return SaManager.getSaHttpTemplate().get(url);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 处理指定消息
|
||||
*
|
||||
@ -95,5 +84,4 @@ public class SaSsoTemplate {
|
||||
return messageHolder.handleMessage(this, message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -23,10 +23,13 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token-SSO 单点登录模块 工具类
|
||||
*
|
||||
* <h2> 请更换为 SaSsoServerUtil 或 SaSsoClientUtil <h2/>
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.30.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class SaSsoUtil {
|
||||
|
||||
// ---------------------- Ticket 操作 ----------------------
|
||||
@ -40,7 +43,7 @@ public class SaSsoUtil {
|
||||
* @return Ticket码
|
||||
*/
|
||||
public static String createTicket(String client, Object loginId, String deviceId) {
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.createTicket(client, loginId, deviceId);
|
||||
return SaSsoServerProcessor.instance.ssoServerTemplate.createTicketAndSave(client, loginId, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,9 +58,6 @@ public class SaSsoConsts {
|
||||
/** SSO 模式3 */
|
||||
public static final int SSO_MODE_3 = 3;
|
||||
|
||||
// /** 消息类型:单点注销 */
|
||||
// public static final String MESSAGE_LOGOUT = "logout";
|
||||
|
||||
/** 消息类型:校验 ticket */
|
||||
public static final String MESSAGE_CHECK_TICKET = "checkTicket";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user