Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ASP.NET Core中返回401而不是302?_C#_Asp.net Core_Asp.net Core Identity - Fatal编程技术网

C# 如何在ASP.NET Core中返回401而不是302?

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

我正在尝试让ASP.NET Core Identity在用户未登录时返回401。我在方法中添加了一个
[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);
        }

    }