1
build / build-push (push) Successful in 1m49s

This commit is contained in:
wanghu
2026-09-04 13:02:23 +08:00
parent e9c4b64240
commit b91fd1b514
@@ -28,7 +28,8 @@ namespace YhCore.WebApi.Auth
/// 调 /serviceValidate 校验(service 即登录时的原访问 URL,含分号段则一并重建,CAS 在末尾追加
/// ?ticket=/&ticket= 回跳)。成功后写入 Cookie 登录态并 302 到分号段 redirectToReferer(hex 解码,
/// 当前形态)/ query redirectToReferer(旧 query 形态兼容)/ returnUrl(更早中继形态兼容)/
/// 原 URL 去 ticket 版(无回跳目标)。</item>
/// 原 URL 去 ticket 版(无回跳目标);显式回跳目标(白名单通过)302 时透传一次性 ticket
/// (目标已有 query 用 &amp;ticket=,否则 ?ticket=——按联调约定供目标页作登录完成信号)。</item>
/// </list>
/// </summary>
public class CasAuthenticationHandler : AuthenticationHandler<CasAuthenticationOptions>
@@ -200,19 +201,26 @@ namespace YhCore.WebApi.Auth
Context.User = principal;
// 回跳原地址:
// 1. query redirectToReferer=<hex>(当前形态:service=原访问 URL 时由 CAS 原样回带)→ 解码跳该目标;
// 2. query returnUrl(旧中继形态 service={回调端点}?returnUrl=… 的历史 URL/缓存,兼容);
// 3. 旧 ;redirectToReferer=<hex> 路径段(更早形态,兼容);
// 1. 路径分号段 ;redirectToReferer=<hex>(当前形态:service=原 URL;redirectToReferer=<hex>,
// CAS 原样回带)→ 解码跳该目标;
// 2. query redirectToReferer=<hex>(ff31293 前的 query 形态 URL/缓存,兼容);
// 3. query returnUrl(更早中继形态 service={回调端点}?returnUrl=…,兼容);
// 4. 都没有(service=纯净原访问 URL 的 notice 形态:CAS 在 service 后追加 ?ticket= 回跳,
// 本请求 Path + 除 ticket 外 query 即登录时原 URL)→ 302 去掉一次性 ticket 落回原地址。
// 允许本地相对路径或同源完整 http(s) URL;非法(外站 host / 协议相对等)回根路径,防开放重定向。
var referer = ResolveQueryRedirectToReferer()
?? ResolveReturnUrl()
?? ParseRedirectToReferer(Context.Request.Path.Value);
// 显式回跳目标(1/2/3)白名单通过时透传一次性票据:目标页按联调约定可凭 ticket 自证登录成功——
// 注意票据已被本次 /serviceValidate 消费(一次性),目标侧不得再拿去 CAS 校验,仅作登录完成信号。
var referer = ParseRedirectToReferer(Context.Request.Path.Value)
?? ResolveQueryRedirectToReferer()
?? ResolveReturnUrl();
string redirect;
if (referer != null)
{
redirect = IsAllowedReturnTarget(referer, AllowedHost()) ? referer : "/";
if (redirect == referer)
{
redirect = AppendTicket(redirect, ticketValue);
}
}
else
{
@@ -223,6 +231,17 @@ namespace YhCore.WebApi.Auth
return AuthenticateResult.NoResult();
}
/// <summary>给回跳目标追加一次性票据(目标已有 query 用 &amp;,否则用 ?)。</summary>
private static string AppendTicket(string url, string ticket)
{
if (string.IsNullOrEmpty(ticket))
{
return url;
}
return url + (url.IndexOf('?') < 0 ? "?" : "&")
+ "ticket=" + Uri.EscapeDataString(ticket);
}
/// <summary>从回调路径中解析 ;redirectToReferer= 后的 hex 并解码;无该段或编码非法返回 null。</summary>
private static string ParseRedirectToReferer(string path)
{