C# 如何在ASP.NET Core中返回401而不是302?
我正在尝试让ASP.NET Core Identity在用户未登录时返回401。我在方法中添加了一个C# 如何在ASP.NET Core中返回401而不是302?,c#,asp.net-core,asp.net-core-identity,C#,Asp.net Core,Asp.net Core Identity,我正在尝试让ASP.NET Core Identity在用户未登录时返回401。我在方法中添加了一个[Authorize]属性,它没有返回401,而是返回302。我尝试了很多建议,但似乎没有任何效果,包括服务。配置和应用程序。使用CookieAuthentication将登录路径设置为null或PathString.Empty好的,在中仔细研究后,我终于找到了一个有效的解决方案。您必须在呼叫服务时添加以下内容。附加信息 services.AddIdentity<ApplicationUse
[Authorize]
属性,它没有返回401,而是返回302。我尝试了很多建议,但似乎没有任何效果,包括服务。配置和应用程序。使用CookieAuthentication
将登录路径设置为null
或PathString.Empty
好的,在中仔细研究后,我终于找到了一个有效的解决方案。您必须在呼叫服务时添加以下内容。附加信息
services.AddIdentity<ApplicationUser, IdentityRole>(o => {
o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
services.AddIdentity(o=>{
o、 Cookies.applicationcokie.AutomaticChallenge=false;
});
服务。配置(选项=>
{
options.Cookies.applicationcokie.LoginPath=新路径字符串(“/”);
options.Cookies.applicationcokie.Events=新建CookieAuthenticationEvents()
{
OnRedirectToLogin=上下文=>
{
if(context.Request.Path.Value.StartsWith(“/api”))
{
context.Response.Clear();
context.Response.StatusCode=401;
返回Task.FromResult(0);
}
context.Response.Redirect(context.RedirectUri);
返回Task.FromResult(0);
}
};
});
资料来源:
自ASP.NET Core 2.x起:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
用于asp.net mvc核心
用这个代替
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;
};
});
如果请求头包含X-request-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);
}
请参见gitHub上的:我在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 Core 3.x(预览)使用身份验证和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;
};
});
services.AddIdentity最终在黑暗中带来了光明
我挠头已经一天多了,尝试了许多不同的变化:
- 覆盖Authorize属性(不再需要在3.x中覆盖太多)
- 使用Cookie指定options.Cookie.EventType(运行时错误)
- options.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme(据说JWT bearer不会重定向到登录页面)
- 当然,还要配置
应用程序okie
(但在调用AddIdentity
之前,该操作不起作用
这一切都不起作用。但有了上面的答案,我终于得到了401未经授权的返回(顺便说一句,应该是未经验证的)在继续中,我将以前的答案合并到以下内容中:
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.助手自定义类
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);
}
}
这是否仍然会将用户重新定向到登录页面?由于302,当单击这些页面时,会重新定向到登录页面。我仍然希望这些页面能够正常工作,但我希望所有机器人都无法通过该调用,这样他们就再也不会调用它了(401/403)。302仍然会告诉他们继续调用它。(这是为那些不支持robots.txt文件的人准备的,我在其中指定“不允许”该url模式)@ganders没有。如果你想让你的应用程序在401上以某种方式运行,你必须自己处理。通常,401应该包括一个描述如何进行身份验证的WWW Authenticate标头。WWW Authenticate
标头必须在401上提供。如果受保护的资源请求不包括身份验证凭据或does不包含允许访问受保护资源的访问令牌,资源服务器必须包含HTTP“WWW Authenticate”响应头字段
这似乎在.NET Core 3.x(预览)中不再存在:/这正是我所需要的。谢谢!在.net core 2.1上工作得很好-尽管我不得不将StartsWith(“/api”)更改为contains(“api”)但在那之后效果很好。我想我现在需要在我的应用程序中做一些事情来检测401,并在任何http请求后相应地重定向。干杯!对我来说,需要设置的是OnRedirectToAccessDenied。另外,你的呼叫服务。附加属性必须在这之前。我相信kroatti的答案应该是被接受的。上面如果您希望ajax请求得到401,但非ajax请求得到重定向,则这种方法会导致问题。根据Mark Perry的回答,您可以添加逻辑来处理这一问题,但对于具有X-request-with:XMLHttpRequest头的请求,此逻辑已经内置到框架中。我为我的项目编写了三种不同的自定义策略。因此,此retu对于我所有的策略,rn 401而不是302?这起作用了。这在框架中是一个多么烦人的功能。如果我们想要重定向,我们会指定它…对我来说,需要设置的是OnRedirectToAccessDenied。这个解决方案在Core 2中运行得非常好!感谢您使用ASP.NET Core 2.0,您可以使用返回任务.CompletedTask;
对于return Task.FromResult(null);
如其他地方所述,请确保这是在调用services.AddIdentity(…)
或AddDefaultIdentity(…)
谢谢,这非常有效。但是,是否有方法返回401和json(类似于{authorize:“Failed”})完美!像charm一样工作这应该是最直接的答案,不会伤害您的代码库。seesh,为什么我之前没有找到您。这不是一个非常有用的答案,因为它要求调用方注入专有的头值。如何修复处理程序代码,以实际遵守Accept:头?我的客户端代码(angular)正在发送“Accept:application/json”,但返回垃圾HTML作为无法解析的响应。服务器端代码是问题所在。对于遵循相同轨迹的任何其他人,我从这里开始,不需要设置“位置”header-这只对3xx状态代码有用Hi@Bernoulli,我使用的是asp.net core 3.1,曾尝试将类似代码放入客户端应用程序中,但不起作用。什么不起作用?它不起作用吗
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);
}
}