C# ASP.NET Core 5.0 - 为啥在使用 [Authorization] 时甚至不调用该方法

Posted

技术标签:

【中文标题】C# ASP.NET Core 5.0 - 为啥在使用 [Authorization] 时甚至不调用该方法【英文标题】:C# ASP.NET Core 5.0 - Why the method is not even called, when [Authorization] is usedC# ASP.NET Core 5.0 - 为什么在使用 [Authorization] 时甚至不调用该方法 【发布时间】:2021-09-23 03:40:21 【问题描述】:

我有 JWT 令牌和 API。

在 startup.cs - 我有 jwt 授权的配置:

public void ConfigureServices(IServiceCollection services)
        
            SetupJWTServices(services);
            services.AddControllers();
            services.AddSwaggerGen(c =>
            
                c.SwaggerDoc("v3", new OpenApiInfo  Title = "MyTitle", Version = "v3" );
                c.OperationFilter<AddSwaggerService>();
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                
                    Description = "JWT Token authorization",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                );
            
            );
        
private static void SetupJWTServices(IServiceCollection services)
        
            string key = "secret Public key Token";      
            var issuer = "myIssuer";
            byte[] publicKey = Convert.FromBase64String(key);
            var ecdsa = ECDsa.Create();
            ecdsa.ImportSubjectPublicKeyInfo(source: publicKey, bytesRead: out _);            
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
            
                options.TokenValidationParameters = new TokenValidationParameters
                
                    ValidateIssuer = true,
                    ValidateAudience = false,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = issuer,
                    ValidAudience = issuer,
                    IssuerSigningKey = new ECDsaSecurityKey(ecdsa),
                    ValidAlgorithms = new[]
                    
                        @"ES256"
                    
                ;
                options.Events = new JwtBearerEvents
                
                    OnAuthenticationFailed = context =>
                    
                        if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        
                            context.Response.Headers.Add("Token-Expired", "true");
                        
                        return Task.CompletedTask;
                    
                ;
            );
        
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => 
                    c.SwaggerEndpoint("/swagger/v3/swagger.json", "MyAPIService");
                );
            
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseAuthentication();
            app.UseEndpoints(endpoints =>
            
                endpoints.MapControllers();
            );
        

然后我在控制器中有方法,我称之为:

[Authorize]
        [HttpGet("CreateNewPassword")]
        public IActionResult CreateNewPassword(string Password)
        
            if (User.Identity.IsAuthenticated)
            
                if (User.Identity is ClaimsIdentity identity)
                
                    _ = identity.Claims;
                
                return Json(new  YourNewHashedPassword = Helpers.GetNewHashedText(Password) );
            
            else
            
                return Json(new  ErrorMessage = "JWT is invalid!" );
            
        

问题是:

如果我将 [Authorize] 放在方法之上 - 该方法甚至不会被执行,当被调用时(来自 swagger 和来自邮递员的相同行为)并自动返回 401

如果我删除 [Authorize] 行为是正确的 - 根据 JWT 令牌 - 所以如果 JWT 从 POSTMAN 无效 - 它返回 401 并带有 ErrorMessage (没关系) - 如果 JWT 令牌从 POSTMAN 是正常的 - 它返回一个新密码(这只是我的测试方法)

但是!当我删除 [Authorize] 并从 swagger 执行调用时 - 总是有消息 401(没有错误消息) - 因为缺少带有 JWT 令牌的标头。

问题是:

我如何使用 [Authorize] - 所以招摇和邮递员将正确执行该方法: 当 JWT 正确时 = 它将以常规方式执行 当 JWT 无效 = 它将返回 401...

【问题讨论】:

我不清楚。您是否希望在没有用户时执行该方法?如果是这样,那么不要使用授权。 我想通过 JWT 获得授权 - 但是当我使用 [Authorize] 时 - 该方法甚至没有执行并立即返回 401 - 所以我希望我在 startup.cs 中有问题 -但我不知道是什么 如果是 JWT ,您应该登录以取回 jwt 令牌。所以你登录的功能,你应该添加注释[AllowAnonymous],然后生成令牌。然后就可以使用token进行授权了。 情况并非如此 - 我有来自另一种方法的 JWT,没关系。问题是已经说明的关键字 [Authorize] 【参考方案1】:

好像认证和授权中间件的顺序不对。 你先有UseAuthorization

app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>

    endpoints.MapControllers();
);

试试这个:

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>

    endpoints.MapControllers();
);

【讨论】:

以上是关于C# ASP.NET Core 5.0 - 为啥在使用 [Authorization] 时甚至不调用该方法的主要内容,如果未能解决你的问题,请参考以下文章

为啥 .Mobile.cshtml 未在 ASP.NET Core C# Razor Pages Web 应用程序中呈现?

如何按照存储库模式在 Asp.Net Core 5.0 项目上实现 .Net Core Identity?

ASP.NET CORE 5.0 Identity 显示当前登录用户

在 ASP.NET Core 5.0 Web API 中实现 DelegatingHandler?

在 Asp.Net Core 5.0 中注册 HttpClient 时注入 ILogger

无法在 ASP.NET Core 5.0 下的 IIS 中托管 CoreWcf