ASP.NET Core 中的授权问题。使用 [Authorize] 属性时始终返回 401 Unauthorized。

40

这是我第一次在ASP.NET Core中创建认证。我使用了这里的教程:TUTORIAL

问题是当我从Postman发送请求时:

Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6I...

针对我的带有 [Authorize] 标记的控制器方法,我总是收到 401 Unauthorized 的错误提示……我看到了下面的评论,似乎也有一些人遇到了类似的问题。我不知道该如何解决这个问题。


3
JwtBearerMiddleware 应该会产生很多日志事件。在 Startup.Configure 方法中添加一个记录器并进行检查。 - Ilya Chumakov
16
@DiPix,如果您在此处发布您的答案,那将会很有帮助,这样我们就可以看到发生了什么。否则,对于其他落在这个页面上的人来说是没有帮助的。 - Ray
1
@Ray的评论上每个赞应该代表着寻找DiPix所做的事情的人们。 :| - Irwin
1
@Irwin 我已经发布了答案 :) - DiPix
2
请重命名或删除此问题,因为您提供的答案与调试无关。 - IvanP
显示剩余3条评论
10个回答

36

根据他人的要求,这是答案:

问题出在 Startup.cs 中中间件的顺序。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    ConfigureAuth(app); // your authorisation configuration

    app.UseMvc();
}

为什么中间件顺序很重要?如果我们先放置app.UseMvc(),那么MVC动作将进入路由,如果它们看到Authorize属性,它们将控制其处理,这就是我们收到401未经授权的错误的原因。

我希望能帮助到大家;)


5
如果您正在使用 ASP.NET Core 3.0 的预览版本,请将 UseMvc 替换为 UseRouting - Scott Page
2
在我的情况下,我忘记在app.UseMvc()之前添加app.UseAuthentication(),这可能是上面的ConfigureAuth(app)调用的内容。 - baltzar
已经快两年了,我还是遇到了这个问题!! - Persk
@BaltzarMattson 你能否提供一个新的回答? - goamn
@goamn 不确定新答案会提供什么,只需确保顺序为:app.UseAuthentication() 然后是 app.UseMvc() - baltzar
@BaltzarMattson 这个答案并不明显,有人必须阅读所有的答案,然后阅读所有的评论,才能理解。由你决定 :) - goamn

27

经过几个小时的研究,我遇到了这个问题...(在 .net 6 上)天哪。谢谢 @eugenecp - ajzbrun

7
如果您正在使用ASP.NET Core 3.0,
请按照以下顺序进行检查: app.UseAuthentication(); app.UseRouting(); //必须在app.UseAuthentication();之后
如果您正在使用ASP.NET Core < 3.0,
只需将app.UseRouting();替换为app.UseMvc(); 例如: app.UseAuthentication(); app.UseMvc();//必须在app.UseAuthentication(); 之后

我认为你弄错了3.0的顺序。正确的顺序可以在以下链接中查看 - https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.0 - Dibzmania

3

在 Startup 类中,我的 ConfigureServices 和 Configure 方法(Asp.Net Core 3.1.0):

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("AllowsAll", builder =>
        {
            builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
        });
    });

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        ...
    });

    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseAuthentication();
    app.UseRouting();
    app.UseAuthorization();

    app.UseCors(options => options.AllowAnyOrigin());

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

我的控制器:

[Authorize]
[EnableCors("AllowsAll")]
[Route("[controller]")]
public class MyController : MyController
{
    ...
}

1
谢谢!谢谢!谢谢!我之前在UseAuthentication()和UseAuthorization()之前使用了UseRouting(),在本地运行时效果很好,但是一旦部署到Web服务器上,就会返回401。我看到有答案说我应该在UseRouting()之前使用UseAuthentication(),所以我试图将UseAuthentication()和UseAuthorization()都放在UseRouting()之前,但这并没有起作用。按照您上面描述的顺序放置这三个函数结束了我一天的头痛。 - mac
1
请标记为答案。 - Matthias Bruns

3

对于 .NET CORE 3.0 或更高版本的用户,在 StartUp.cs 文件的 "configure" 中使用此命令。

        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();

1
此答案已经存在于正上方。 - jelde015

3
在我的情况下,我正在按照 coreApiangularClient 教程操作,但每次都会出现未经授权的错误。而且,在我的情况下,Angular 应用程序正在 Core Api 项目下运行。
所以我改变了顺序,现在它可以正常工作了。
   public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
    {

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();


        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });


        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });


         loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        // global cors policy
        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials());

    }

2

我通过在Startup类的Configure方法中更改UseAuthentication()的顺序和UseRouting()来解决了我的问题。

修改前

app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();

之后

app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();

0
在我的情况下,我也使用了 app.MapWhen(code) 和 app.UseAuthentication(); 应该在 mapWhen 之前放置,像这样:
app.UseAuthentication();
app.MapWhen();
app.UseMvc();

希望这个能有所帮助。

0

在中间件的顺序之外,令牌的参数必须与身份验证参数(具体来说,密钥)匹配。

我犯了一个错误,就是我在两个地方使用了不同的密钥,这导致返回状态码401。

分享一些可能有助于其他人的代码截图(.net core 3.1)。

Startup.cs > ConfigureServices() startup.cs file

Login Controller逻辑 Token generation logic


-4
我的解决方案是检查启动类 Configure 方法中中间件和其他内容的正确顺序。通常情况下,使用 app.UseMvc();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接