首页 文章

缺少cookie时,.NET核心返回500而不是401

提问于
浏览
1

我有一个使用cookie身份验证的.NET核心API . 它由具有自己的登录路径的PWA / SPA访问 .

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
...
    services.AddIdentity<MyUser, MyRole>(options =>
    {
        ...

        // Use cookie authentication
        var expiresIn = new TimeSpan(1, 0, 0); // 1 hour timeout
        var c = options.Cookies.ApplicationCookie;
        c.AuthenticationScheme = "appSchemeName";
        c.CookieName = "appCookieName";
        c.AutomaticAuthenticate = true;

        // If this is true auth failures become redirects
        c.AutomaticChallenge = false;
        c.SlidingExpiration = true;
        c.ExpireTimeSpan = expiresIn;

        // Store sessions in the cache with the same TTL as the cookie
        c.SessionStore = new MyRedisSessionStore(expiresIn);
    });
    ...
}

public void Configure(...) 
{
    ...
    app.UseIdentity();
    ...
    app.UseMvc();
}

在我的客户端JS中,当验证cookie无效或丢失时,我期望401,并且在这种情况下显示登录表单 .

但是,当没有有效cookie的用户访问标记为 [Authorize] 的控制器时,他们会收到500状态错误:

InvalidOperationException:没有配置身份验证处理程序来处理该方案:自动

如果我改变 c.AutomaticChallenge = true; 然后我得到302重定向到 {site}/Account/Login?ReturnUrl={api resource it was trying to load} . 's weird because that'不是有效路线,我没有设置它 .

如何解决此问题,以便未经身份验证的用户在服务器上获得401而不是500例外 .

我意识到我可以覆盖它并使用自定义响应编写自己的身份验证,但必须有一种方法可以使内置的 [Authorize] 返回正确的HTTP状态代码 .

2 回答

  • 3

    当我使用Postman来测试我的 endpoints 时,我遇到了这个问题 .

    如果您查看 OnRedirectToLogin 事件的source code,您可以看到它正在检查请求是否是AJAX请求 . 要 IsAjaxRequest 返回 trueX-Requested-With 标头需要 XMLHttpRequest 作为其值 .

    如果您碰巧使用Postman进行测试,则必须手动应用X-Requested-With以及正确的值:

    Image for Postman Settings (can't embed images, yet)

    最后,如果您没有其他需要设置的特殊配置,这就是您的_1730809应该是什么样子:

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true
    });
    
  • 1

    我有一个解决方案,因为我有代码可以工作,但它是可怕的,不可能是处理这个问题的最佳方法 .

    我当前的代码给出了500服务器错误(当 AutomaticChallenge = false 时)或302重定向(当 AutomaticChallenge = true 时) . 两者在我的SPA中都没用,因为500太通用了,而302重定向到一个不存在的页面透明,我在客户端JS得到404 .

    我的修复是使用302,然后覆盖 Response

    // Make ASP.NET give us the 302 redirect when cookie is missing/broke
    c.AutomaticChallenge = true;
    
    c.Events = new CookieAuthenticationEvents
    {
        // Override the 302 redirection with the 401 we actually want 
        OnRedirectToLogin = context =>
        {
            context.Response.StatusCode = 401;
            return Task.FromResult(0); ;
        }
    };
    

    这是有效的,所以它是这个问题的答案,但它是一个可怕的黑客中间件,并没有表现我想要它 .

相关问题