JWT Authentication .Net core [Authorize] 属性被控制器忽略

Posted

技术标签:

【中文标题】JWT Authentication .Net core [Authorize] 属性被控制器忽略【英文标题】:JWT Authentication .Net core [Authorize] Attribute Ignored by Controller 【发布时间】:2021-11-24 04:13:41 【问题描述】:

我正在尝试在具有 Angular 8 前端和 .Net Core 后端的应用中实现基于 JWT 的身份验证。我加了

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

services.AddAuthentication(opt =>

在启动类中。我使用[Authorize] 属性修饰了控制器方法。但是当我尝试在没有任何标记的情况下点击控制器方法时,它允许进入控制器方法。

启动

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)
        
            var jwtSettings = Configuration.GetSection("JwtSettings");
            services.AddAuthentication(opt =>
            
                opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            ).AddJwtBearer(options =>
            
                options.TokenValidationParameters = new TokenValidationParameters
                
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = jwtSettings.GetSection("validIssuer").Value,
                    ValidAudience = jwtSettings.GetSection("validAudience").Value,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.GetSection("securityKey").Value))
                ;
            );
            services.AddSignalR();

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

            // In production, the Angular files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            
                configuration.RootPath = "ClientApp/dist";
            );

            // requires using Microsoft.Extensions.Options
            services.Configure<DatabaseSettings>(
                Configuration.GetSection(nameof(DatabaseSettings)));

            services.AddSingleton<IDatabaseSettings>(sp =>
                sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);

            services.AddSingleton<FileService>();

            services.AddSingleton<InternalReportService>();


            services.AddTransient<MailService>();
            services.AddMvc(option => option.EnableEndpointRouting = false);


        

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        
            app.UseRouting();
            app.UseMvc();
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            
            else
            
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            
            app.UseHttpsRedirection();
            app.UseStaticFiles();          
            app.UseAuthentication();
            app.UseAuthorization();             

            app.UseEndpoints(endpoints =>
            
                endpoints.MapHub<CoreHub>("/corehub");
                endpoints.MapControllerRoute("default", "controller=Home/action=Index");

            );

            app.UseSpa(spa =>
            
                  
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                
                    spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");

                
            );
        
    

控制器

[Authorize]
public async Task UploadFile(IFormFile file)

// Do Stuff

【问题讨论】:

尝试使用这个 services.AddMvcCore() 而不是 services.AddMvc() 您没有共享创建 JWT 或持久化令牌的代码。 https://code-maze.com/authentication-aspnetcore-jwt-1/ 【参考方案1】:

嗯,你已经配置了你的 API 的认证部分,现在你需要用同样的方式配置授权......

你可以这样配置:

services.AddAuthorization(options =>

    options.AddPolicy("Default", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build());

    options.AddPolicy("Admin", new AuthorizationPolicyBuilder()
        .RequireRole("Admin")
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build());
);

然后你就可以使用属性了

[Authorize("User")]
[Authorize("Admin")]

在您的控制器或特定端点上。

如果您希望将此默认策略放在所有端点/控制器上并仅控制 if 的“AllowAnonymous”部分,您可以这样做:

services.AddMvc()
        .AddMvcOptions(options =>
        
            // Mark all endpoints with the default policy
            options.Filters.Add(new AuthorizeFilter("Default"));
        )

【讨论】:

应该是正确答案。 为什么必须定义角色?我的应用程序只需要有效的 Token 即可运行,不需要角色。 你不需要需要一个角色,只需定义一个默认的 -no named- 策略,正如@GibbOne 已经使用opts.DefaultPolicy = new AuthorizationPolicyBuilder(opts.DefaultPolicy).RequireAuthenticatedUser() 展示的那样,事实上,如果你愿意,你可以同时使用两者,同样适用于全局过滤器 事实上,默认策略是静态的,我想只要调用services.AddAuthorization() 就可以了,否则你必须配置它【参考方案2】:

根据您的身份验证方案,您应该以这种方式指定属性: [Authorize(AuthenticationSchemes = "Bearer")] 这应该可以按您的预期工作

【讨论】:

谢谢...但这不起作用。 @techno 你能提供你的控制器的完整代码吗? 问题已解决。我打错了方法。 @techno 你的意思是有些答案是正确的吗?或者你的意思是整个问题与问题无关? 添加承载实际上解决了这个问题。但真正的问题是别的。【参考方案3】:

我一般加DefaultSchema

services.AddAuthentication(opt =>

    opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    opt.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
//...

和授权。

services.AddAuthorization(opts =>

    opts.DefaultPolicy = new AuthorizationPolicyBuilder(opts.DefaultPolicy)
          .RequireAuthenticatedUser()
//...

【讨论】:

以上是关于JWT Authentication .Net core [Authorize] 属性被控制器忽略的主要内容,如果未能解决你的问题,请参考以下文章

在c#asp.net core web api中创建jwt令牌[重复]

将 JWT Bearer Authentication Web API 与 Asp.Net Core 2.0 结合使用的问题

JWT Bearer Authentication 不从标头中读取 Token

.NET 6.0中使用Identity框架实现JWT身份认证与授权

与 ejabberd 一起使用的 JWT 秘密?

.NET Core 2.0 身份和 jwt?