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 仍用原始路径);未经过该中间件时回退解析当前