"Token has expired" 不触发 401 错误代码

"Token has expired" doesn't trigger 401 error code

我正在使用未捕获的异常处理程序:

this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) =>
{
    res.WriteErrorBody(ex);
    Log.Error(ex);
    res.EndRequest(skipHeaders: true);
});

有时,当我有一段时间没有使用该项目时,我会收到一个“令牌已过期”异常,该异常会触发此处理程序。它不会 return 向我的前端发送 401 代码,因此 front-end 不会丢弃登录数据并提示用户再次登录。没有响应数据。

这是headers

Request URL: https://localhost:44308/json/reply/BlogsLookUpRequest
Referrer Policy: strict-origin-when-cross-origin
access-control-allow-origin: https://localhost:4200
content-length: 0
date: Sun, 25 Jul 2021 02:54:31 GMT
server: Kestrel
x-powered-by: ASP.NET
:authority: localhost:44308
:method: POST
:path: /json/reply/BlogsLookUpRequest
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en,en-GB;q=0.9
authorization: Bearer omitted
cache-control: no-cache
content-length: 165
content-type: application/json
cookie: omitted
pragma: no-cache
referer: https://localhost:4200/
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36

我试过了:

this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) =>
{
    res.WriteErrorBody(ex);
    Log.Error(ex);
    if (ex.GetType() == typeof(TokenException))
    {
        res.StatusCode = 401;
    }
    res.EndRequest(skipHeaders: true);
});

但是没有响应所以没有状态码。

我在这里缺少一些理解,因为这并不总是发生。我将前端编码为在出现 401 错误时直接登录,这似乎在某些登录到期的情况下发生。

我是不是做错了什么?使用过期令牌时,如何让 SS 返回 return 401?

这是堆栈跟踪:

at ServiceStack.Auth.JwtAuthProviderReader.AssertJwtPayloadIsValid(JsonObject jwtPayload) in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\Auth\JwtAuthProviderReader.cs:line 779
   at ServiceStack.Auth.JwtAuthProviderReader.CreateSessionFromPayload(IRequest req, JsonObject jwtPayload) in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\Auth\JwtAuthProviderReader.cs:line 752
   at ServiceStack.Auth.JwtAuthProviderReader.PreAuthenticateAsync(IRequest req, IResponse res) in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\Auth\JwtAuthProviderReader.cs:line 538
   at ServiceStack.AuthenticateAttribute.<PreAuthenticateAsync>d__20.MoveNext() in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 207
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work1\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) in E:\A\_work1\s\src\mscorlib\src\System\Runtime\CompilerServices\TaskAwaiter.cs:line 155
   at ServiceStack.AuthenticateAttribute.<ExecuteAsync>d__12.MoveNext() in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 77
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work1\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at ServiceStack.ServiceStackHost.<ApplyRequestFiltersSingleAsync>d__386.MoveNext() in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 183
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work1\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) in E:\A\_work1\s\src\mscorlib\src\System\Runtime\CompilerServices\TaskAwaiter.cs:line 155
   at ServiceStack.ServiceStackHost.<ApplyRequestFiltersAsync>d__385.MoveNext() in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 145
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work1\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) in E:\A\_work1\s\src\mscorlib\src\System\Runtime\CompilerServices\TaskAwaiter.cs:line 155
   at ServiceStack.Host.Handlers.GenericHandler.<ProcessRequestAsync>d__12.MoveNext() in C:\BuildAgent\work81147c480f4a2f\src\ServiceStack\Host\Handlers\GenericHandler.cs:line 57

过期令牌抛出 TokenException 实现 IHasStatusCode 执行 return 401 Unauthorized HTTP 错误。

我们的测试以及所有依赖过期令牌的服务客户端 Automatically refreshing Access Tokens 都证实了这一点 returning 401 Unauthorized 错误响应。

您的响应 Headers 不包含状态代码,因此无法确定实际 return 编辑的响应状态代码是什么。我建议使用 Fiddler,这样您就可以捕获原始 HTTP Headers,其中将包含响应状态代码。

如果您的自定义错误处理逻辑干扰了它,我建议您不要尝试 interfere/handle 任何实现 IHasStatusCode 的异常,例如:

this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) =>
{
    if (ex is IHasStatusCode) return;
    res.WriteErrorBody(ex);
    Log.Error(ex);
    res.EndRequest(skipHeaders: true);
});