diff --git a/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs b/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs
index d5568bc..434e62d 100644
--- a/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs
+++ b/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs
@@ -188,7 +188,7 @@ namespace YhCore.WebApi.Auth
if (!string.IsNullOrEmpty(revisitTicket) && CasHex.IsAllowedRedirectTarget(revisitReferer, AllowedHost()))
{
Context.User = cookieResult.Principal;
- Response.Redirect(revisitReferer);
+ Response.Redirect(StripTicketParams(revisitReferer));
return AuthenticateResult.NoResult();
}
return AuthenticateResult.Success(cookieResult.Ticket!);
@@ -249,8 +249,10 @@ namespace YhCore.WebApi.Auth
?? ResolveReturnUrl();
if (referer != null)
{
- // 有显式回跳目标:302 到纯解码地址(不追加 ticket 等任何参数)。
- var target = CasHex.IsAllowedRedirectTarget(referer, AllowedHost()) ? referer : "/";
+ // 有显式回跳目标:302 到纯解码地址(不追加任何参数),并剥离目标上历史残留的
+ // ticket 参数(SPA 的 yschreferer 携带 window.location.href,曾在死循环中累积
+ // 多个 ticket 进 fragment;回跳时清掉,避免污染的地址在页面间继续传播)。
+ var target = CasHex.IsAllowedRedirectTarget(referer, AllowedHost()) ? StripTicketParams(referer) : "/";
Response.Redirect(target);
return AuthenticateResult.NoResult();
}
@@ -273,6 +275,27 @@ namespace YhCore.WebApi.Auth
private static bool IsRootPath(string path)
=> string.IsNullOrEmpty(path) || path == "/";
+ ///
+ /// 剥离回跳目标 URL 上的 ticket 参数(query 与 #fragment 内均处理)。
+ /// SPA 地址的死循环残留形如 #/?ticket=ST-x&ticket=ST-y;按 (?|&)ticket=[^&#]* 正则全局删除,
+ /// 再清理删除后悬空的连接符,保证 URL 结构完好。
+ ///
+ private static string StripTicketParams(string url)
+ {
+ if (string.IsNullOrEmpty(url) || url.IndexOf("ticket=", StringComparison.OrdinalIgnoreCase) < 0)
+ {
+ return url;
+ }
+ var stripped = System.Text.RegularExpressions.Regex.Replace(
+ url, "[?&]ticket=[^]*", string.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+ stripped = stripped.Replace("?&", "?").Replace("&&", "&");
+ if (stripped.EndsWith('&') || stripped.EndsWith('?'))
+ {
+ stripped = stripped.Remove(stripped.Length - 1);
+ }
+ return stripped;
+ }
+
///
/// 解析 ;redirectToReferer= 分号段的回跳目标:优先 PathMatrixSegmentMiddleware 存入 Items 的
/// hex(分号段已从路由路径剥离,回调重建 service 仍用原始路径);未经过该中间件时回退解析当前