如何 return 401 而不是 ASP.NET Core 中的 302?
How to return 401 instead of 302 in ASP.NET Core?
我正在尝试在用户未登录时将 ASP.NET 核心身份设置为 return 401。我在我的方法中添加了一个 [Authorize]
属性,而不是returning 401 它 returns 302。我尝试了很多建议,但似乎没有任何效果,包括 services.Configure
和 app.UseCookieAuthentication
将 LoginPath
设置为null
或 PathString.Empty
.
好的,在 asp.net core unit tests 中仔细研究后,我终于找到了一个可行的解决方案。您必须将以下内容添加到对 services.AddIdentity
的调用中
services.AddIdentity<ApplicationUser, IdentityRole>(o => {
o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
services.Configure<IdentityOptions>(options =>
{
options.Cookies.ApplicationCookie.LoginPath = new PathString("/");
options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.Value.StartsWith("/api"))
{
context.Response.Clear();
context.Response.StatusCode = 401;
return Task.FromResult(0);
}
context.Response.Redirect(context.RedirectUri);
return Task.FromResult(0);
}
};
});
来源:
自 ASP.NET 核心 2.x:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
对于asp.netmvc核心
改用这个
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api")
&& context.Response.StatusCode == StatusCodes.Status200OK)
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
如果请求 header 包含 X-Requested-With: XMLHttpRequest 状态代码将是 401 而不是 302
private static bool IsAjaxRequest(HttpRequest request)
{
return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
}
对我来说 ASP.NET Core 2.2.0 只有这个有效:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(
options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api")
&& context.Response.StatusCode == StatusCodes.Status200OK)
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
}
);
对于 ASP.NET 核心 3.x(预览版)使用 Identity with Cookie 身份验证,这就是诀窍:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<IdentityContext>()
.AddDefaultTokenProviders()
.AddRoles<IdentityRole>();
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
这就是我们随处可见的不同变体。但是,这里的重点是必须指定 ConfigureApplicationCookie
AFTER AddIdentity
. "sad" 但这是真的。这终于在黑暗中带来了光明。
我摸索了一天多,尝试了许多不同的变体:
- 覆盖 Authorize 属性(不再需要在 3.x 中覆盖)
- 使用 Cookie 指定 options.Cookie.EventType(运行时错误)
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme(据说 JWT 承载不会重定向到登录页面)
- 当然还有配置
ApplicationCookie
(但在调用 AddIdentity
之前不起作用。
这一切都没有用。但是有了上面的答案,我终于得到了 401 Unauthorized 返回(顺便说一句,应该是 Unauthenticated)
接下来,我将之前的答案合并为以下内容:
1. Startup.cs
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToAccessDenied = context =>
{
if (wlt_AjaxHelpers.IsAjaxRequest(context.Request))
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
2。帮手定制 class
public static class wlt_AjaxHelpers
{
public static bool IsAjaxRequest( HttpRequest request )
{
return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
}
}
我正在尝试在用户未登录时将 ASP.NET 核心身份设置为 return 401。我在我的方法中添加了一个 [Authorize]
属性,而不是returning 401 它 returns 302。我尝试了很多建议,但似乎没有任何效果,包括 services.Configure
和 app.UseCookieAuthentication
将 LoginPath
设置为null
或 PathString.Empty
.
好的,在 asp.net core unit tests 中仔细研究后,我终于找到了一个可行的解决方案。您必须将以下内容添加到对 services.AddIdentity
services.AddIdentity<ApplicationUser, IdentityRole>(o => {
o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
services.Configure<IdentityOptions>(options =>
{
options.Cookies.ApplicationCookie.LoginPath = new PathString("/");
options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.Value.StartsWith("/api"))
{
context.Response.Clear();
context.Response.StatusCode = 401;
return Task.FromResult(0);
}
context.Response.Redirect(context.RedirectUri);
return Task.FromResult(0);
}
};
});
来源:
自 ASP.NET 核心 2.x:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
对于asp.netmvc核心 改用这个
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api")
&& context.Response.StatusCode == StatusCodes.Status200OK)
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
如果请求 header 包含 X-Requested-With: XMLHttpRequest 状态代码将是 401 而不是 302
private static bool IsAjaxRequest(HttpRequest request)
{
return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
}
对我来说 ASP.NET Core 2.2.0 只有这个有效:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(
options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api")
&& context.Response.StatusCode == StatusCodes.Status200OK)
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
}
);
对于 ASP.NET 核心 3.x(预览版)使用 Identity with Cookie 身份验证,这就是诀窍:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<IdentityContext>()
.AddDefaultTokenProviders()
.AddRoles<IdentityRole>();
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
这就是我们随处可见的不同变体。但是,这里的重点是必须指定 ConfigureApplicationCookie
AFTER AddIdentity
. "sad" 但这是真的。这
我摸索了一天多,尝试了许多不同的变体:
- 覆盖 Authorize 属性(不再需要在 3.x 中覆盖)
- 使用 Cookie 指定 options.Cookie.EventType(运行时错误)
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme(据说 JWT 承载不会重定向到登录页面)
- 当然还有配置
ApplicationCookie
(但在调用AddIdentity
之前不起作用。
这一切都没有用。但是有了上面的答案,我终于得到了 401 Unauthorized 返回(顺便说一句,应该是 Unauthenticated)
接下来,我将之前的答案合并为以下内容:
1. Startup.cs
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToAccessDenied = context =>
{
if (wlt_AjaxHelpers.IsAjaxRequest(context.Request))
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
2。帮手定制 class
public static class wlt_AjaxHelpers
{
public static bool IsAjaxRequest( HttpRequest request )
{
return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
}
}