HttpClient (C#) 拦截未经授权 (401) 并重定向

3
我在我的Blazor项目中使用Auth0进行用户登录,并在WebAPI端点中额外对用户进行身份验证,以提供用于后续调用的jwt。这一切都很顺利。
如果用户的Auth0登录过期,用户会被正确地重定向到登录页面。
问题是当jwt过期时。用户仍然在Web应用程序中进行身份验证,但当他们访问WebAPI时,他们会得到一个预期的未经授权(401)的响应。
我希望最终能够实现刷新令牌的代码,但现在我愿意通过重定向到一个注销控制器来强制用户重新进行身份验证。
我尝试过从继承自HttpClientHandler的自定义处理程序进行重定向。
var unauthorizedHandler = new UnauthorizedHandler();
var httpClient = new HttpClient(unauthorizedHandler);


public class UnauthorizedHandler : HttpClientHandler
{
    private IHttpContextAccessor _httpContextAccessor;

    public void Add(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        
        if (response.StatusCode == HttpStatusCode.Unauthorized)
        {
            _httpContextAccessor.HttpContext.Response.Redirect("/Identity/Logout", true);
        }

        return response;
    }
}

重定向结果为:System.InvalidOperationException: StatusCode 无法设置,因为响应已经开始。

我还使用了 NSwag 生成的 C# 客户端,并尝试在 ProcessResponse 部分方法中进行类似的重定向,但是得到了相同/类似的错误消息。

如果我捕获异常并通过 NavigationManager 在实际的 Blazor 页面中进行重定向,它可以正常工作,但是我希望以一种横切的方式处理这个问题。

我如何在 HttpClient 中拦截未经授权的错误并自动重定向?


请查看这个链接:https://stackoverflow.com/a/56204930/2557855 - undefined
那个问题/答案是针对 .Net Core 2.x 的。使用答案代码的修改版本,重定向仍然导致相同的错误。 - undefined
1个回答

2
我过去处理过类似的问题。这是我建议你采取的一种可能的方法。 首先,错误表明一旦http响应开始,就无法修改它以添加重定向状态码,所以基于这一点,尝试以下操作:
  1. 使用基于事件的机制或自定义异常来通知UI层,也就是你的Blazor页面,已收到授权状态
  2. 我在代码中没有看到,但以防万一,请确保UnauthorizedHandler使用DI获取所需的依赖项
  3. 使用“NavigationManager”实际执行重定向
所以总结一下,我的想法是尝试类似于这样的方法:
public class UnauthorizedHandler : HttpClientHandler
{
    public event Action UnauthorizedStatusReceived;

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        if (response.StatusCode == HttpStatusCode.Unauthorized)
        {
            // Notice this line
            UnauthorizedStatusReceived?.Invoke();
        }

        return response;
    }
}

然后注册处理程序和IHttpContextAncessor:
services.AddSingleton<UnauthorizedHandler>();
services.AddHttpContextAccessor();

最后,在您的 Blazor 组件中订阅 UnauthorizedStatusReceived 事件,并使用 NavigationManager 进行重定向。
@inject UnauthorizedHandler UnauthorizedHandler
@inject NavigationManager NavigationManager

protected override void OnInitialized()
{
    UnauthorizedHandler.UnauthorizedStatusReceived += HandleUnauthorized;
}

private void HandleUnauthorized()
{
    NavigationManager.NavigateTo("/Identity/Logout");
}

希望这能帮助你解决问题或者让你更接近解决问题的方法。

看起来这个会成功!谢谢你的帮助。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接