mirror of
https://gitee.com/dromara/sa-token.git
synced 2026-02-27 16:50:24 +08:00
refactor: 新增 TicketModel 对象,以便在 ticket 中储存更多信息
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Model: Ticket 码
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public class TicketModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6541180061782004705L;
|
||||
|
||||
/**
|
||||
* ticket 码
|
||||
*/
|
||||
public String ticket;
|
||||
|
||||
/**
|
||||
* 应用标识
|
||||
*/
|
||||
public String client;
|
||||
|
||||
/**
|
||||
* 设备 id
|
||||
*/
|
||||
public String deviceId;
|
||||
|
||||
/**
|
||||
* 对应 loginId
|
||||
*/
|
||||
public Object loginId;
|
||||
|
||||
/**
|
||||
* 创建时间,13位时间戳
|
||||
*/
|
||||
public long createTime;
|
||||
|
||||
/**
|
||||
* 构建一个
|
||||
*/
|
||||
public TicketModel() {
|
||||
this.createTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个
|
||||
* @param ticket 授权码
|
||||
* @param client 应用id
|
||||
* @param loginId 对应的账号id
|
||||
* @param deviceId 重定向地址
|
||||
*/
|
||||
public TicketModel(String ticket, String client, String deviceId, Object loginId) {
|
||||
this();
|
||||
this.ticket = ticket;
|
||||
this.client = client;
|
||||
this.deviceId = deviceId;
|
||||
this.loginId = loginId;
|
||||
}
|
||||
|
||||
|
||||
// get set
|
||||
|
||||
/**
|
||||
* 获取 ticket 码
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getTicket() {
|
||||
return this.ticket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 ticket 码
|
||||
*
|
||||
* @param ticket /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public TicketModel setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 应用标识
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getClient() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 应用标识
|
||||
*
|
||||
* @param client /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public TicketModel setClient(String client) {
|
||||
this.client = client;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 设备 id
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getDeviceId() {
|
||||
return this.deviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 设备 id
|
||||
*
|
||||
* @param deviceId /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public TicketModel setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 对应 loginId
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public Object getLoginId() {
|
||||
return this.loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 对应 loginId
|
||||
*
|
||||
* @param loginId /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public TicketModel setLoginId(Object loginId) {
|
||||
this.loginId = loginId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 创建时间,13位时间戳
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public long getCreateTime() {
|
||||
return this.createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 创建时间,13位时间戳
|
||||
*
|
||||
* @param createTime /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public TicketModel setCreateTime(long createTime) {
|
||||
this.createTime = createTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TicketModel{" +
|
||||
"ticket='" + ticket + '\'' +
|
||||
", client='" + client + '\'' +
|
||||
", deviceId='" + deviceId + '\'' +
|
||||
", loginId=" + loginId +
|
||||
", createTime=" + createTime +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import cn.dev33.satoken.sso.message.SaSsoMessage;
|
||||
import cn.dev33.satoken.sso.message.handle.server.SaSsoMessageCheckTicketHandle;
|
||||
import cn.dev33.satoken.sso.message.handle.server.SaSsoMessageSignoutHandle;
|
||||
import cn.dev33.satoken.sso.model.SaSsoClientInfo;
|
||||
import cn.dev33.satoken.sso.model.TicketModel;
|
||||
import cn.dev33.satoken.sso.util.SaSsoConsts;
|
||||
import cn.dev33.satoken.strategy.SaStrategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
@@ -51,38 +52,38 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
// ---------------------- Ticket 操作 ----------------------
|
||||
|
||||
/**
|
||||
* 保存 Ticket 关联的 loginId
|
||||
* @param ticket ticket码
|
||||
* @param loginId 账号id
|
||||
* 保存 Ticket
|
||||
* @param ticketModel /
|
||||
*/
|
||||
public void saveTicket(String ticket, Object loginId) {
|
||||
// 保存 ticket -> loginId 的关系
|
||||
public void saveTicket(TicketModel ticketModel) {
|
||||
long ticketTimeout = getServerConfig().getTicketTimeout();
|
||||
SaManager.getSaTokenDao().set(splicingTicketSaveKey(ticket), String.valueOf(loginId), ticketTimeout);
|
||||
SaManager.getSaTokenDao().setObject(splicingTicketSaveKey(ticketModel.getTicket()), ticketModel, ticketTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存 Ticket 索引 (id 反查 ticket)
|
||||
*
|
||||
* @param client 应用端
|
||||
* @param ticket ticket码
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void saveTicketIndex(String ticket, Object loginId) {
|
||||
public void saveTicketIndex(String client, String ticket, Object loginId) {
|
||||
long ticketTimeout = getServerConfig().getTicketTimeout();
|
||||
SaManager.getSaTokenDao().set(splicingTicketIndexKey(loginId), String.valueOf(ticket), ticketTimeout);
|
||||
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 关联的 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
|
||||
@@ -92,29 +93,45 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
if(ticket == null) {
|
||||
return;
|
||||
}
|
||||
SaManager.getSaTokenDao().delete(splicingTicketSaveKey(ticket));
|
||||
SaManager.getSaTokenDao().deleteObject(splicingTicketSaveKey(ticket));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Ticket索引
|
||||
*
|
||||
* @param client 应用标识
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void deleteTicketIndex(Object loginId) {
|
||||
public void deleteTicketIndex(String client, Object loginId) {
|
||||
if(loginId == null) {
|
||||
return;
|
||||
}
|
||||
SaManager.getSaTokenDao().delete(splicingTicketIndexKey(loginId));
|
||||
SaManager.getSaTokenDao().delete(splicingTicketIndexKey(client, loginId));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 删除 Ticket 关联的 client
|
||||
// *
|
||||
// * @param ticket Ticket码
|
||||
// */
|
||||
// public void deleteTicketToClient(String ticket) {
|
||||
// if(ticket == null) {
|
||||
// return;
|
||||
// }
|
||||
// SaManager.getSaTokenDao().delete(splicingTicketToClientSaveKey(ticket));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 删除 Ticket 关联的 client
|
||||
* 查询 ticket ,如果 ticket 码无效则返回 null
|
||||
*
|
||||
* @param ticket Ticket码
|
||||
* @return 账号id
|
||||
*/
|
||||
public void deleteTicketToClient(String ticket) {
|
||||
if(ticket == null) {
|
||||
return;
|
||||
public TicketModel getTicket(String ticket) {
|
||||
if(SaFoxUtil.isEmpty(ticket)) {
|
||||
return null;
|
||||
}
|
||||
SaManager.getSaTokenDao().delete(splicingTicketToClientSaveKey(ticket));
|
||||
return SaManager.getSaTokenDao().getObject(splicingTicketSaveKey(ticket), TicketModel.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,10 +140,11 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
* @return 账号id
|
||||
*/
|
||||
public Object getLoginId(String ticket) {
|
||||
if(SaFoxUtil.isEmpty(ticket)) {
|
||||
TicketModel ticketModel = getTicket(ticket);
|
||||
if(ticketModel == null) {
|
||||
return null;
|
||||
}
|
||||
return SaManager.getSaTokenDao().get(splicingTicketSaveKey(ticket));
|
||||
return ticketModel.getLoginId();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,28 +159,30 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 指定 loginId 其所属的 ticket 值
|
||||
* 查询 指定 client、loginId 其所属的 ticket 值
|
||||
*
|
||||
* @param client 应用
|
||||
* @param loginId 账号id
|
||||
* @return Ticket值
|
||||
*/
|
||||
public String getTicketValue(Object loginId) {
|
||||
public String getTicketValue(String client, Object loginId) {
|
||||
if(loginId == null) {
|
||||
return null;
|
||||
}
|
||||
return SaManager.getSaTokenDao().get(splicingTicketIndexKey(loginId));
|
||||
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 关联的 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));
|
||||
// }
|
||||
|
||||
//
|
||||
/**
|
||||
@@ -174,11 +194,15 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
public String createTicket(Object loginId, String client) {
|
||||
// 创建 Ticket
|
||||
String ticket = randomTicket(loginId);
|
||||
TicketModel ticketModel = new TicketModel();
|
||||
ticketModel.setTicket(ticket);
|
||||
ticketModel.setClient(client);
|
||||
ticketModel.setLoginId(loginId);
|
||||
// TODO ticketModel.setDeviceId();
|
||||
|
||||
// 保存 Ticket
|
||||
saveTicket(ticket, loginId);
|
||||
saveTicketIndex(ticket, loginId);
|
||||
saveTicketToClient(ticket, client);
|
||||
saveTicket(ticketModel);
|
||||
saveTicketIndex(client, ticket, loginId);
|
||||
|
||||
// 返回 Ticket
|
||||
return ticket;
|
||||
@@ -201,31 +225,32 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
*/
|
||||
public Object checkTicket(String ticket, String client) {
|
||||
// 读取 loginId
|
||||
String loginId = SaManager.getSaTokenDao().get(splicingTicketSaveKey(ticket));
|
||||
|
||||
if(loginId != null) {
|
||||
|
||||
// 解析出这个 ticket 关联的 Client
|
||||
String ticketClient = getTicketToClient(ticket);
|
||||
|
||||
// 校验 client 参数是否正确,即:创建 ticket 的 client 和当前校验 ticket 的 client 是否一致
|
||||
if(SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
||||
// 如果提供的是通配符,直接越过 client 校验
|
||||
} else if (SaFoxUtil.isEmpty(client) && SaFoxUtil.isEmpty(ticketClient)) {
|
||||
// 如果提供的和期望的两者均为空,则通过校验
|
||||
} else {
|
||||
// 开始详细比对
|
||||
if(SaFoxUtil.notEquals(client, ticketClient)) {
|
||||
throw new SaSsoException("该 ticket 不属于 client=" + client + ", ticket 值: " + ticket).setCode(SaSsoErrorCode.CODE_30011);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除 ticket 信息,使其只有一次性有效
|
||||
deleteTicket(ticket);
|
||||
deleteTicketIndex(loginId);
|
||||
deleteTicketToClient(ticket);
|
||||
TicketModel ticketModel = getTicket(ticket);
|
||||
if(ticketModel == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object loginId = ticketModel.getLoginId();
|
||||
String ticketClient = ticketModel.getClient();
|
||||
|
||||
// 解析出这个 ticket 关联的 Client
|
||||
|
||||
// 校验 client 参数是否正确,即:创建 ticket 的 client 和当前校验 ticket 的 client 是否一致
|
||||
if(SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
||||
// 如果提供的是通配符,直接越过 client 校验
|
||||
} else if (SaFoxUtil.isEmpty(client) && SaFoxUtil.isEmpty(ticketClient)) {
|
||||
// 如果提供的和期望的两者均为空,则通过校验
|
||||
} else {
|
||||
// 开始详细比对
|
||||
if(SaFoxUtil.notEquals(client, ticketClient)) {
|
||||
throw new SaSsoException("该 ticket 不属于 client=" + client + ", ticket 值: " + ticket).setCode(SaSsoErrorCode.CODE_30011);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除 ticket 信息,使其只有一次性有效
|
||||
deleteTicket(ticket);
|
||||
deleteTicketIndex(ticket, loginId);
|
||||
|
||||
//
|
||||
return loginId;
|
||||
}
|
||||
@@ -333,7 +358,7 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
checkRedirectUrl(client, redirect);
|
||||
|
||||
// 删掉 旧Ticket
|
||||
deleteTicket(getTicketValue(loginId));
|
||||
deleteTicket(getTicketValue(client, loginId));
|
||||
|
||||
// 创建 新Ticket
|
||||
String ticket = createTicket(loginId, client);
|
||||
@@ -714,22 +739,27 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
|
||||
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:Ticket 查 所属的 client
|
||||
// * @param ticket ticket值
|
||||
// * @return key
|
||||
// */
|
||||
// public String splicingTicketToClientSaveKey(String ticket) {
|
||||
// return getStpLogic().getConfigOrGlobal().getTokenName() + ":ticket-client:" + ticket;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 拼接key:账号Id 反查 Ticket
|
||||
*
|
||||
* @param client 应用标识
|
||||
* @param id 账号id
|
||||
* @return key
|
||||
*/
|
||||
public String splicingTicketIndexKey(Object id) {
|
||||
return getStpLogic().getConfigOrGlobal().getTokenName() + ":id-ticket:" + id;
|
||||
public String splicingTicketIndexKey(String client, Object id) {
|
||||
if(SaFoxUtil.isEmpty(client) || SaSsoConsts.CLIENT_WILDCARD.equals(client)) {
|
||||
client = SaSsoConsts.CLIENT_ANON;
|
||||
}
|
||||
return getStpLogic().getConfigOrGlobal().getTokenName() + ":id-ticket:" + client + ":" + id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,10 +50,11 @@ public class SaSsoUtil {
|
||||
|
||||
/**
|
||||
* 删除 Ticket索引
|
||||
* @param loginId 账号id
|
||||
* @param client 应用 id
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public static void deleteTicketIndex(Object loginId) {
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate.deleteTicketIndex(loginId);
|
||||
public static void deleteTicketIndex(String client, Object loginId) {
|
||||
SaSsoServerProcessor.instance.ssoServerTemplate.deleteTicketIndex(client, loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,6 +48,9 @@ public class SaSsoConsts {
|
||||
/** client 身份,* 代表通配,可以解析出所有 client 的 ticket */
|
||||
public static final String CLIENT_WILDCARD = "*";
|
||||
|
||||
/** client 身份,代表匿名 client */
|
||||
public static final String CLIENT_ANON = "anon";
|
||||
|
||||
/** SSO 模式1 */
|
||||
public static final int SSO_MODE_1 = 1;
|
||||
/** SSO 模式2 */
|
||||
|
||||
Reference in New Issue
Block a user