【问题标题】:UseJwtBearerAuthentication returning HTTP 500 on token expiryUseJwtBearerAuthentication 在令牌到期时返回 HTTP 500
【发布时间】:2016-08-06 09:47:22
【问题描述】:

我正在使用这样的 UseJwtBearerAuthentication

app.UseJwtBearerAuthentication(options =>
{
   options.Authority = Configuration["Urls:IdentityServer"];
   options.RequireHttpsMetadata = false;

   options.Audience = Configuration["Urls:IdentityServer"] + "/resources";
   options.AutomaticAuthenticate = true;
   options.Events = new JwtBearerEvents
   {
        OnAuthenticationFailed = context =>
        {
          context.HandleResponse();   
          return Task.FromResult(0);
        }
   }; 
});

在 Visual Studio 的诊断窗口中,我看到以下 2 个异常:

System.IdentityModel.Tokens.dll 中的 System.IdentityModel.Tokens.SecurityTokenExpiredException'(“IDX10223:生命周期验证失败。令牌已过期。

下线

抛出异常:Microsoft.AspNet.Authentication.dll 中的“System.ArgumentNullException”(“值不能为空。”)

如何返回 HTTP 401 Unauthorized?

【问题讨论】:

    标签: asp.net-mvc asp.net-core jwt identityserver3


    【解决方案1】:

    这是一个known bug。可悲的是,the workaround you could use in beta8 不再有效 in RC1

    您唯一的选择是编写一个捕获异常的中间件,以防止服务器返回 500 响应。当然,它很丑陋并且可能会隐藏重要的异常,但它是唯一适用于 RC1 的已知解决方法。

    这是一个例子:

    app.Use(next => async context =>
    {
        try
        {
            await next(context);
        }
    
        catch
        {
            // If the headers have already been sent, you can't replace the status code.
            // In this case, re-throw the exception to close the connection.
            if (context.Response.HasStarted)
            {
                throw;
            }
    
            // Rethrow the exception if it was not caused by IdentityModel.
            if (!context.Items.ContainsKey("jwt-workaround"))
            {
                throw;
            }
    
            context.Response.StatusCode = 401;
        }
    });
    
    app.UseJwtBearerAuthentication(new JwtBearerOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        RequireHttpsMetadata = false,
    
        Audience = "http://localhost:54540/",
        Authority = "http://localhost:54540/",
    
        Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                context.HttpContext.Items["jwt-workaround"] = null;
    
                return Task.FromResult(0);
            }
        };
    });
    

    【讨论】:

    • 此代码是否将所有异常都返回为 401?抱歉,代码不太明白。
    • 当然。您可以浏览 IdentityModel 存储库并列出 JWT 安全令牌处理程序可能抛出的所有异常,而不是捕获所有异常。
    • 如果您只想捕获“过期令牌”错误,请更新 catch 块以仅拦截 SecurityTokenExpiredException 异常。
    • 我更新了我的答案以重新抛出不是由 JWT 中间件引起的异常。
    • 你捕获 SecurityTokenExpiredException 似乎是要走的路。此外,可能建议删除OnAuthenticationFailed
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 2013-03-20
    • 2019-10-05
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多