diff --git a/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs b/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs
index 1106e16..d5568bc 100644
--- a/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs
+++ b/src/YhCore.WebApi/Auth/Cas/CasAuthenticationHandler.cs
@@ -247,20 +247,32 @@ namespace YhCore.WebApi.Auth
var referer = ResolveRedirectToReferer()
?? ResolveQueryRedirectToReferer()
?? ResolveReturnUrl();
- string redirect;
if (referer != null)
{
- redirect = CasHex.IsAllowedRedirectTarget(referer, AllowedHost()) ? referer : "/";
+ // 有显式回跳目标:302 到纯解码地址(不追加 ticket 等任何参数)。
+ var target = CasHex.IsAllowedRedirectTarget(referer, AllowedHost()) ? referer : "/";
+ Response.Redirect(target);
+ return AuthenticateResult.NoResult();
}
- else
+
+ // 无显式回跳目标(无 referer 挑战:service=原访问 URL,CAS 原样带 ticket 回调):
+ // - 根路径回调(如 /?ticket=ST-xxx):Cookie 已写入、Context.User 已同步,直接返回放行管道,
+ // 由根端点当场渲染登录态页面(200,零重定向)——即"验票登录且不再重定向";
+ // 刷新/重放该地址时走 Cookie 恢复(票据不再参与),不会重复验票失败 401,杜绝重定向循环。
+ // - 其余路径回调:仍 302 去掉 ticket 的干净原地址(清理地址栏,防刷新重复验票)。
+ var cleanUrl = BuildServiceUrlFromOriginalPath();
+ if (IsRootPath(ResolveOriginalPath()) && CasHex.IsAllowedRedirectTarget(cleanUrl, AllowedHost()))
{
- redirect = BuildServiceUrlFromOriginalPath();
- redirect = CasHex.IsAllowedRedirectTarget(redirect, AllowedHost()) ? redirect : "/";
+ return AuthenticateResult.NoResult();
}
- Response.Redirect(redirect);
+ Response.Redirect(CasHex.IsAllowedRedirectTarget(cleanUrl, AllowedHost()) ? cleanUrl : "/");
return AuthenticateResult.NoResult();
}
+ /// 是否根路径(无 referer 挑战的 service=根地址形态,回调形如 /?ticket=ST-xxx)。
+ private static bool IsRootPath(string path)
+ => string.IsNullOrEmpty(path) || path == "/";
+
///
/// 解析 ;redirectToReferer= 分号段的回跳目标:优先 PathMatrixSegmentMiddleware 存入 Items 的
/// hex(分号段已从路由路径剥离,回调重建 service 仍用原始路径);未经过该中间件时回退解析当前