ASP.NET Core 2.0禁用自动挑战

时间:2017-08-25 09:15:59

标签: c# authentication asp.net-core asp.net-core-mvc

将我的ASP.NET Core项目升级到2.0后,尝试访问受保护的端点不再返回401,而是重定向到(不存在的)端点以尝试让用户进行身份验证。

所需的行为是应用程序只返回401.以前我会在配置身份验证时设置AutomaticChallenge = false,但根据this article,设置不再相关(实际上它不是已经存在了。)

我的身份验证配置如下:

Startup.cs.ConfigureServices():

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(o =>
                {
                    o.Cookie.Name = options.CookieName;
                    o.Cookie.Domain = options.CookieDomain;
                    o.SlidingExpiration = true;
                    o.ExpireTimeSpan = options.CookieLifetime;
                    o.TicketDataFormat = ticketFormat;
                    o.CookieManager = new CustomChunkingCookieManager();
                });

配置():

app.UseAuthentication();

如何禁用自动质询,以便在用户未经过身份验证时应用程序返回401?

8 个答案:

答案 0 :(得分:24)

正如其他一些答案所指出的那样,不再有使用cookie身份验证关闭自动质询的设置。解决方案是覆盖OnRedirectToLogin

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
         {                 
             options.Events.OnRedirectToLogin = context =>
             {
                 context.Response.Headers["Location"] = context.RedirectUri;
                 context.Response.StatusCode = 401;
                 return Task.CompletedTask;
             };
         });

将来可能会发生变化:https://github.com/aspnet/Security/issues/1394

答案 1 :(得分:20)

经过一些研究,我发现我们可以通过下面的方法处理这个问题:

我们可以添加Identity和JWT两种身份验证方案;并使用身份方案进行身份验证并使用JWT模式进行质询,JWT在挑战时不会重定向到任何登录路由。

services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>();

services.AddAuthentication((cfg =>
{
    cfg.DefaultScheme = IdentityConstants.ApplicationScheme;
    cfg.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})).AddJwtBearer();

答案 2 :(得分:4)

根据this文章:

在1.x中, AutomaticAuthenticate AutomaticChallenge 属性旨在在单个身份验证方案上设置。没有好办法来实施这一点。

在2.0中,这两个属性已作为单个 AuthenticationOptions 实例上的标记删除,并已移至基本AuthenticationOptions类中。可以在Startup.cs的 ConfigureServices 方法中的 AddAuthentication 方法调用中配置属性

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);

或者,使用AddAuthentication方法的重载版本来设置多个属性。在以下重载方法示例中,默认方案设置为CookieAuthenticationDefaults.AuthenticationScheme。也可以在您的个人 [授权] 属性或授权政策中指定身份验证方案。

services.AddAuthentication(options => {
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});

如果满足下列条件之一,则在2.0中定义默认方案:

  • 您希望用户自动登录
  • 您使用 [授权] 属性或授权策略而未指定 方案

此规则的一个例外是 AddIdentity 方法。此方法为您添加cookie,并将默认的身份验证和质询方案设置为应用程序cookie IdentityConstants.ApplicationScheme 。此外,它还将默认登录方案设置为外部cookie IdentityConstants.ExternalScheme

希望这对你有所帮助。

答案 3 :(得分:4)

与@Serverin类似,设置Application Cookie的OnRedirectToLogin工作,但必须在startup.cs中的services.AddIdentity之后的语句中完成:ConfigureServices:

services.ConfigureApplicationCookie(options => {
  options.Events.OnRedirectToLogin = context => {
    context.Response.Headers["Location"] = context.RedirectUri;
    context.Response.StatusCode = 401;
    return Task.CompletedTask;
  };
});

答案 4 :(得分:3)

这是CookieAuthenticationEvents.OnRedirectToLogin的源代码:

public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToLogin { get; set; } = context =>
{
    if (IsAjaxRequest(context.Request))
    {
        context.Response.Headers["Location"] = context.RedirectUri;
        context.Response.StatusCode = 401;
    }
    else
    {
        context.Response.Redirect(context.RedirectUri);
    }
    return Task.CompletedTask;
};

您可以添加&#34; X-Requested-With:XMLHttpRequest&#34;从客户端进行API调用时,请求标头。

答案 5 :(得分:1)

另一种方法(对DI /测试更友好)是使用AuthenticationSchemeOptions.EventsType(另一种答案points at it here)。这将使您能够将其他组件拉入解决过程。

这是一个包括注册和解析的示例,该示例停止默认的重定向以登录未经身份验证的请求,而仅返回一个硬401。它还有一个插槽,用于存放可能需要了解未经身份验证的请求的任何其他依赖项。

Startup.cs中:

services
    .AddAuthentication("MyAuthScheme")
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
    {
        options.EventsType = typeof(MyEventsWrapper);
    };

...

services.AddTransient<MyEventsWrapper>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

然后,在MyEventsWrapper.cs中:

public class MyEventsWrapper : CookieAuthenticationEvents
{
    private readonly IHttpContextAccessor _accessor;
    private readonly IDependency _otherDependency;

    public MyEventsWrapper(IHttpContextAccessor accessor,
                           IDependency otherDependency)
    {
        _accessor = accessor;
        _otherDependency = otherDependency;
    }

    public override async Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context)
    {
        context.Response.Headers.Remove("Location");
        context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        await _otherDependency.Cleanup(_accessor.HttpContext);
    }
}

答案 6 :(得分:1)

我发现在大多数情况下,解决方案是覆盖

  

OnRedirectToLogin

但是在我的应用程序中,我使用了多种身份验证策略,而Fill的覆盖对我而言无效。在我的情况下,解决方案是添加一个简单的中间件来重定向传入的请求。

OnRedirectToLogin

答案 7 :(得分:0)

我不确定如何生成401错误,但是如果您使用:

o.AccessDeniedPath = "{path to invalid}";

这将允许您在挑战失败时重定向到某个地方。