当添加Authorize属性时,Web API Core返回404错误

43

我是 .net core 的新手,并且尝试创建实现jwt进行身份验证和授权的web api core。

在Startup类中,我进行了如下配置:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {

        services.AddDbContext<MandarinDBContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("MyConnection")));

        services.AddIdentity<User, Role>()
        .AddEntityFrameworkStores<MyDBContext>()
        .AddDefaultTokenProviders();

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = false,
                        ValidateAudience = false,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = "yourdomain.com",
                        ValidAudience = "yourdomain.com",
                        IssuerSigningKey = new SymmetricSecurityKey(
                            Encoding.UTF8.GetBytes("My secret goes here"))
                    };

                    options.RequireHttpsMetadata = false;
                });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        // Add application services.
        services.AddTransient<IUserService, UserService>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        app.UseAuthentication();
        app.UseMvc();
    }
}

但是当我尝试调用以下操作时:

    [Authorize]
    [HttpGet]
    [Route("api/Tokens")]
    public IActionResult TestAuthorization()
    {
        return Ok("You're Authorized");
    }

我收到了404未找到的错误。如果我删除授权属性,它能够正常运行。

您能指导我解决这个问题吗?


也许这可以帮助解决问题:https://github.com/openiddict/openiddict-core/issues/498 - Peter B
如果您启用了cookie身份验证,它可能会将您重定向到一个未找到的页面,否则您只会得到一个友好的401-此请求的授权已被拒绝。 - Nick Kovalsky
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] 这是解决方案。 - hosam hemaily
7个回答

74

当您的API未经授权并且重定向URL不存在时,会出现这种情况。 当身份验证失败时,Web API将发送401代码。如果您正在客户端处理此代码并对授权失败进行重定向,则请确保重定向的URL存在。 此外,请不要在处理身份验证方法(登录/注册)的控制器中添加[Authorize]属性。 问题出在Authorize属性上。由于您正在使用JWT身份验证方案,因此您的authorize属性应该如下所示:

    [Authorize(AuthenticationSchemes = "Bearer")]
    [HttpGet]
    [Route("api/Tokens")]
    public IActionResult TestAuthorization()
    {
        return Ok("You're Authorized");
    }

要将其设置为默认身份验证方案,请将AddIdentity更改为AddIdentityCore。这里有一篇非常好的文章。

在仅 API 的 ASP.NET Core 项目中使用 JwtBearer 身份验证


不,我没有在客户端处理它,我正在使用PostMan进行测试。 - Simple Code
1
options.AccessDeniedPath = "/Identity/Account/AccessDenied"; 你的startup.cs里的configure services代码中有类似这样的吗? - Code Name Jack
不,我没有这样的配置,我正在使用有效的JWT令牌测试我的端点。 - Simple Code
1
非常感谢,现在它可以工作了。但我有一个问题,我能否在不需要为每次需要指定授权属性提供AuthenticationSchemes参数的情况下进行配置? - Simple Code

11

我和你一样遇到了同样的问题,我通过修改 ConfigureServices 解决了这个问题。

来自于这里:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(..)

转化为这样

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

谢谢!这解决了我在尝试在.NET 6 Core Minimal REST API中使用CookieAuthenticationDefaults.AuthenticationScheme.AddCookie()时遇到的特定404错误代码(而不是401)问题。 - RedMatt

3

当您使用JwtBearer令牌时,您可以将以下代码片段添加到ConfigureServices中:

  services.AddControllers(opt => {
            var policy = new AuthorizationPolicyBuilder("Bearer").RequireAuthenticatedUser().Build();
            opt.Filters.Add(new AuthorizeFilter(policy));
        })

这将在整个应用程序中设置Bearer身份验证策略,并要求对每个终点进行身份验证的用户。 此外,您不需要在方法上放置[Authorize],如果您希望它们对未经身份验证的用户可用,您可以在端点和控制器上放置[AllowAnonymous]。

注意:这适用于.NET Core 3.1。


1
虽然这个方法确实可行,但是当我需要覆盖并指定一个带有角色的授权属性时,我无法让它起作用,因此最终使用了被接受的答案。 - Gabe

1
在我的情况下,我以错误的顺序添加了配置。要先添加身份验证,再添加认证。

0

只使用授权属性就可以使它与我一起工作

[Authorize]
    public class WeatherForecastController : ControllerBase
    {...}

在 ConfigureServices 中通过这种方式

services.AddIdentity<ApplicationUser, ApplicationRole>(options => options.SignIn.RequireConfirmedAccount = true)
               .AddEntityFrameworkStores<OkazContext>();

            var key = Encoding.ASCII.GetBytes(Configuration["JwtConfig:Secret"]);

            var tokenValidationParams = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = true,
                RequireExpirationTime = false,
                ClockSkew = TimeSpan.Zero
            };

            services.AddSingleton(tokenValidationParams);

            services.AddAuthentication(options => {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(jwt => {
                jwt.SaveToken = true;
                jwt.TokenValidationParameters = tokenValidationParams;
            });

0
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

这是解决方案


0
可能是因为在Program.cs中,身份验证服务的注册在授权服务的注册之后。
必须按照以下方式进行注册:
builder.Services.ConfigureIdentity();
builder.Services.ConfigureAuthorization(builder.Configuration);

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