mirror of
https://gitee.com/dromara/sa-token.git
synced 2024-12-01 19:37:42 +08:00
新增sso client 登录记录功能
This commit is contained in:
parent
08659f1fa8
commit
7652a51592
@ -316,7 +316,7 @@ public class SaSsoClientConfig implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaSsoConfig ["
|
||||
return "SaSsoClientConfig ["
|
||||
+ "mode=" + mode
|
||||
+ ", client=" + client
|
||||
+ ", serverUrl=" + serverUrl
|
||||
|
@ -64,6 +64,11 @@ public class SaSsoServerConfig implements Serializable {
|
||||
*/
|
||||
public Boolean isHttp = false;
|
||||
|
||||
/**
|
||||
* 在 Access-Session 上记录 Client 信息的最高数量(-1=无限),超过此值将进行自动清退处理,先进先出
|
||||
*/
|
||||
public int maxRegClient = 32;
|
||||
|
||||
/**
|
||||
* 是否校验参数签名(方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
*/
|
||||
@ -154,6 +159,22 @@ public class SaSsoServerConfig implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return maxLoginClient 在 Access-Session 上记录 Client 信息的最高数量(-1=无限),超过此值将进行自动清退处理,先进先出
|
||||
*/
|
||||
public int getMaxRegClient() {
|
||||
return maxRegClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxRegClient 在 Access-Session 上记录 Client 信息的最高数量(-1=无限),超过此值将进行自动清退处理,先进先出
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaSsoServerConfig setMaxRegClient(int maxRegClient) {
|
||||
this.maxRegClient = maxRegClient;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 是否校验参数签名(方便本地调试用的一个配置项,生产环境请务必为true)
|
||||
*
|
||||
@ -191,6 +212,7 @@ public class SaSsoServerConfig implements Serializable {
|
||||
+ ", allowUrl=" + allowUrl
|
||||
+ ", isSlo=" + isSlo
|
||||
+ ", isHttp=" + isHttp
|
||||
+ ", maxRegClient=" + maxRegClient
|
||||
+ ", isCheckSign=" + isCheckSign
|
||||
+ "]";
|
||||
}
|
||||
|
@ -24,10 +24,20 @@ package cn.dev33.satoken.sso.model;
|
||||
*/
|
||||
public class SaSsoClientModel {
|
||||
|
||||
/**
|
||||
* 此 client 登录模式(1=模式一,2=模式二,3=模式三)
|
||||
*/
|
||||
public int mode;
|
||||
|
||||
/**
|
||||
* 客户端标识
|
||||
*/
|
||||
public String client;
|
||||
public String client;
|
||||
|
||||
/**
|
||||
* 此次登录 token 值
|
||||
*/
|
||||
public String tokenValue;
|
||||
|
||||
/**
|
||||
* 单点注销回调url
|
||||
@ -37,7 +47,12 @@ public class SaSsoClientModel {
|
||||
/**
|
||||
* 此 client 注册信息的时间,13位时间戳
|
||||
*/
|
||||
public Long regTime;
|
||||
public long regTime;
|
||||
|
||||
/**
|
||||
* 此账号有记录以来为第几次登录,默认从0开始递增
|
||||
*/
|
||||
public int index;
|
||||
|
||||
public SaSsoClientModel() {
|
||||
}
|
||||
@ -48,6 +63,27 @@ public class SaSsoClientModel {
|
||||
this.regTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 此 client 登录模式(1=模式一,2=模式二,3=模式三)
|
||||
*
|
||||
* @return mode 此 client 登录模式(1=模式一,2=模式二,3=模式三)
|
||||
*/
|
||||
public int getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 此 client 登录模式(1=模式一,2=模式二,3=模式三)
|
||||
*
|
||||
* @param mode 此 client 登录模式(1=模式一,2=模式二,3=模式三)
|
||||
* @return /
|
||||
*/
|
||||
public SaSsoClientModel setMode(int mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 客户端标识
|
||||
*
|
||||
@ -61,9 +97,31 @@ public class SaSsoClientModel {
|
||||
* 设置 客户端标识
|
||||
*
|
||||
* @param client 客户端标识
|
||||
* @return /
|
||||
*/
|
||||
public void setClient(String client) {
|
||||
public SaSsoClientModel setClient(String client) {
|
||||
this.client = client;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,9 +137,11 @@ public class SaSsoClientModel {
|
||||
* 设置 单点注销回调url
|
||||
*
|
||||
* @param ssoLogoutCall 单点注销回调url
|
||||
* @return /
|
||||
*/
|
||||
public void setSsoLogoutCall(String ssoLogoutCall) {
|
||||
public SaSsoClientModel setSsoLogoutCall(String ssoLogoutCall) {
|
||||
this.ssoLogoutCall = ssoLogoutCall;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,7 +149,7 @@ public class SaSsoClientModel {
|
||||
*
|
||||
* @return regTime 此 client 注册信息的时间,13位时间戳
|
||||
*/
|
||||
public Long getRegTime() {
|
||||
public long getRegTime() {
|
||||
return this.regTime;
|
||||
}
|
||||
|
||||
@ -97,17 +157,42 @@ public class SaSsoClientModel {
|
||||
* 设置 此 client 注册信息的时间,13位时间戳
|
||||
*
|
||||
* @param regTime 此 client 注册信息的时间,13位时间戳
|
||||
* @return /
|
||||
*/
|
||||
public void setRegTime(Long regTime) {
|
||||
public SaSsoClientModel setRegTime(long regTime) {
|
||||
this.regTime = regTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 此账号有记录以来为第几次登录,默认从0开始递增
|
||||
*
|
||||
* @return regTime 此账号有记录以来为第几次登录,默认从0开始递增
|
||||
*/
|
||||
public long getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 此账号有记录以来为第几次登录,默认从0开始递增
|
||||
*
|
||||
* @param index 此账号有记录以来为第几次登录,默认从0开始递增
|
||||
* @return /
|
||||
*/
|
||||
public SaSsoClientModel setIndex(int index) {
|
||||
this.index = index;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaSsoClientModel{" +
|
||||
"client='" + client + '\'' +
|
||||
"mode=" + mode +
|
||||
", client='" + client + '\'' +
|
||||
", tokenValue='" + tokenValue + '\'' +
|
||||
", ssoLogoutCall='" + ssoLogoutCall + '\'' +
|
||||
", regTime='" + regTime + '\'' +
|
||||
", regTime=" + regTime +
|
||||
", index=" + index +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,9 @@ public class ParamName {
|
||||
/** Client端单点注销时-回调URL 参数名称 */
|
||||
public String ssoLogoutCall = "ssoLogoutCall";
|
||||
|
||||
/** 是否为超过 maxRegClient 的自动注销 */
|
||||
public String autoLogout = "autoLogout";
|
||||
|
||||
public String name = "name";
|
||||
public String pwd = "pwd";
|
||||
|
||||
|
@ -283,13 +283,25 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
|
||||
SaSession session = getStpLogic().getSessionByLoginId(loginId);
|
||||
|
||||
// 取
|
||||
// 取出原来的
|
||||
List<SaSsoClientModel> scmList = session.get(SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_, ArrayList::new);
|
||||
|
||||
// 加
|
||||
scmList.add(new SaSsoClientModel(client, sloCallbackUrl));
|
||||
// 将 新登录client 加入到集合中
|
||||
SaSsoClientModel scm = new SaSsoClientModel();
|
||||
scm.mode = 3;
|
||||
scm.client = client;
|
||||
scm.ssoLogoutCall = sloCallbackUrl;
|
||||
scm.regTime = System.currentTimeMillis();
|
||||
scm.index = calcNextIndex(scmList);
|
||||
scmList.add(scm);
|
||||
|
||||
// 存
|
||||
// 如果登录的client数量超过了限制,则将最早的一个登录进行清退
|
||||
if(scmList.size() > getServerConfig().getMaxRegClient()) {
|
||||
SaSsoClientModel removeScm = scmList.remove(0);
|
||||
notifyClientLogout(loginId, removeScm, true);
|
||||
}
|
||||
|
||||
// 存入持久库
|
||||
session.set(SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_, scmList);
|
||||
}
|
||||
|
||||
@ -305,31 +317,85 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
return;
|
||||
}
|
||||
|
||||
SaSsoServerConfig ssoConfig = getServerConfig();
|
||||
|
||||
// step.1 遍历通知 Client 端注销会话
|
||||
List<SaSsoClientModel> scmList = session.get(SaSsoConsts.SSO_CLIENT_MODEL_LIST_KEY_, ArrayList::new);
|
||||
scmList.forEach(scm -> {
|
||||
// url
|
||||
String sloCallUrl = scm.getSsoLogoutCall();
|
||||
|
||||
// 参数
|
||||
Map<String, Object> paramsMap = new TreeMap<>();
|
||||
paramsMap.put(paramName.client, scm.getClient());
|
||||
paramsMap.put(paramName.loginId, loginId);
|
||||
String signParamsStr = getSignTemplate(scm.getClient()).addSignParamsAndJoin(paramsMap);
|
||||
|
||||
// 拼接
|
||||
String finalUrl = SaFoxUtil.joinParam(sloCallUrl, signParamsStr);
|
||||
|
||||
// 发起请求
|
||||
ssoConfig.sendHttp.apply(finalUrl);
|
||||
notifyClientLogout(loginId, scm, false);
|
||||
});
|
||||
|
||||
// step.2 Server端注销
|
||||
getStpLogic().logout(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知指定账号的指定客户端注销
|
||||
* @param loginId 指定账号
|
||||
* @param scm 客户端信息对象
|
||||
* @param autoLogout 是否为超过 maxRegClient 的自动注销
|
||||
*/
|
||||
public void notifyClientLogout(Object loginId, SaSsoClientModel scm, boolean autoLogout) {
|
||||
|
||||
// 如果给个null值,不进行任何操作
|
||||
if(scm == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果是模式二登录的
|
||||
if(scm.mode == SaSsoConsts.SSO_MODE_2) {
|
||||
// 获取登录 token
|
||||
String tokenValue = scm.tokenValue;
|
||||
if(SaFoxUtil.isEmpty(tokenValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 注销此 token
|
||||
getStpLogic().logoutByTokenValue(scm.tokenValue);
|
||||
}
|
||||
|
||||
// 如果是模式三登录的
|
||||
else if(scm.mode != SaSsoConsts.SSO_MODE_3) {
|
||||
// url
|
||||
String sloCallUrl = scm.getSsoLogoutCall();
|
||||
if(SaFoxUtil.isEmpty(sloCallUrl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 参数
|
||||
Map<String, Object> paramsMap = new TreeMap<>();
|
||||
paramsMap.put(paramName.client, scm.getClient());
|
||||
paramsMap.put(paramName.loginId, loginId);
|
||||
paramsMap.put(paramName.autoLogout, autoLogout);
|
||||
String signParamsStr = getSignTemplate(scm.getClient()).addSignParamsAndJoin(paramsMap);
|
||||
|
||||
// 拼接
|
||||
String finalUrl = SaFoxUtil.joinParam(sloCallUrl, signParamsStr);
|
||||
|
||||
// 发起请求
|
||||
getServerConfig().sendHttp.apply(finalUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算下一个 index 值
|
||||
* @param scmList /
|
||||
* @return /
|
||||
*/
|
||||
private int calcNextIndex(List<SaSsoClientModel> scmList) {
|
||||
// 如果目前还没有任何登录记录,则直接返回0
|
||||
if(scmList == null || scmList.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
// 获取目前最大的index值
|
||||
int maxIndex = scmList.get(scmList.size() - 1).index;
|
||||
|
||||
// 如果已经是 int 最大值了,则直接返回0
|
||||
if(maxIndex == Integer.MAX_VALUE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 否则返回最大值+1
|
||||
return maxIndex++;
|
||||
}
|
||||
|
||||
// ---------------------- 构建URL ----------------------
|
||||
|
||||
|
@ -45,4 +45,11 @@ public class SaSsoConsts {
|
||||
/** 表示请求没有得到任何有效处理 {msg: "not handle"} */
|
||||
public static final String NOT_HANDLE = "{\"msg\": \"not handle\"}";
|
||||
|
||||
/** SSO 模式1 */
|
||||
public static final int SSO_MODE_1 = 1;
|
||||
/** SSO 模式2 */
|
||||
public static final int SSO_MODE_2 = 2;
|
||||
/** SSO 模式3 */
|
||||
public static final int SSO_MODE_3 = 3;
|
||||
|
||||
}
|
||||
|
@ -15,11 +15,13 @@
|
||||
*/
|
||||
package cn.dev33.satoken.solon.sso;
|
||||
|
||||
import cn.dev33.satoken.config.SaSsoConfig;
|
||||
import cn.dev33.satoken.sso.SaSsoManager;
|
||||
import cn.dev33.satoken.sso.SaSsoProcessor;
|
||||
import cn.dev33.satoken.sso.template.SaSsoTemplate;
|
||||
import cn.dev33.satoken.sso.template.SaSsoUtil;
|
||||
import cn.dev33.satoken.sso.config.SaSsoClientConfig;
|
||||
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
|
||||
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
|
||||
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
|
||||
import cn.dev33.satoken.sso.template.SaSsoClientTemplate;
|
||||
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
|
||||
import org.noear.solon.annotation.Bean;
|
||||
import org.noear.solon.annotation.Condition;
|
||||
import org.noear.solon.annotation.Configuration;
|
||||
@ -40,21 +42,33 @@ public class SaSsoAutoConfigure implements InitializingBean {
|
||||
|
||||
@Override
|
||||
public void afterInjection() throws Throwable {
|
||||
appContext.subBeansOfType(SaSsoTemplate.class, bean->{
|
||||
SaSsoUtil.ssoTemplate = bean;
|
||||
SaSsoProcessor.instance.ssoTemplate = bean;
|
||||
appContext.subBeansOfType(SaSsoServerTemplate.class, bean->{
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate = bean;
|
||||
});
|
||||
appContext.subBeansOfType(SaSsoClientTemplate.class, bean->{
|
||||
SaSsoClientProcessor.instance.ssoClientTemplate = bean;
|
||||
});
|
||||
|
||||
appContext.subBeansOfType(SaSsoConfig.class, bean->{
|
||||
SaSsoManager.setConfig(bean);
|
||||
appContext.subBeansOfType(SaSsoServerConfig.class, bean->{
|
||||
SaSsoManager.setServerConfig(bean);
|
||||
});
|
||||
appContext.subBeansOfType(SaSsoClientConfig.class, bean->{
|
||||
SaSsoManager.setClientConfig(bean);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 SSO 配置Bean
|
||||
* 获取 SSO Server 配置Bean
|
||||
* */
|
||||
@Bean
|
||||
public SaSsoConfig getConfig(@Inject(value = "${sa-token.sso}",required = false) SaSsoConfig ssoConfig) {
|
||||
public SaSsoServerConfig getConfig(@Inject(value = "${sa-token.sso-server}",required = false) SaSsoServerConfig ssoConfig) {
|
||||
return ssoConfig;
|
||||
}
|
||||
/**
|
||||
* 获取 SSO Client 配置Bean
|
||||
* */
|
||||
@Bean
|
||||
public SaSsoClientConfig getClientConfig(@Inject(value = "${sa-token.sso-client}",required = false) SaSsoClientConfig ssoConfig) {
|
||||
return ssoConfig;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user