ASP.NET Core Authorize属性不适用于JWT

And*_*son 24 c# asp.net-core asp.net-core-webapi

我想在ASP.Net Core中实现基于JWT的安全性.我现在要做的就是在Authorization标题中读取持有者令牌,并根据我的标准验证它们.我不需要(也不想)包含ASP.Net Identity.事实上,我试图避免使用尽可能多的MVC添加的东西,除非我真的需要它们.

我创建了一个最小的项目,它演示了这个问题.要查看原始代码,只需查看编辑历史记录即可.我希望此示例拒绝所有/ api/icons请求,除非它们为AuthorizationHTTP标头提供相应的承载令牌.该示例实际上允许所有请求.

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Routing;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System;
using Newtonsoft.Json.Serialization;

namespace JWTSecurity
{
    public class Startup
    {
        public IConfigurationRoot Configuration { get; set; }

        public Startup(IHostingEnvironment env)
        {
            IConfigurationBuilder builder = new ConfigurationBuilder().SetBasePath(env.ContentRootPath);
            Configuration = builder.Build();
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();
            services.AddAuthentication();
            services.AddMvcCore().AddJsonFormatters(options => options.ContractResolver = new CamelCasePropertyNamesContractResolver());
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();
            app.UseJwtBearerAuthentication(new JwtBearerOptions
            {
                AutomaticAuthenticate = true,
                AutomaticChallenge = true,
                TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("supersecretkey")),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                }
            });
            app.UseMvc(routes => routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器/ IconsController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace JWTSecurity.Controllers
{
    [Route("api/[controller]")]
    public class IconsController : Controller
    {
        [Authorize]
        public IActionResult Get()
        {
            return Ok("Some content");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

And*_*son 51

找到了!

主要问题在于这一行:

services.AddMvcCore().AddJsonFormatters(options => options.ContractResolver = new CamelCasePropertyNamesContractResolver());
Run Code Online (Sandbox Code Playgroud)

我注意到,从AddMvcCore()切换到AddMvc(),授权突然开始工作!在深入了解ASP.NET源代码后,看看是什么AddMvc(),我意识到我需要第二次调用IMvcBuilder.AddAuthorization().

services.AddMvcCore()
    .AddAuthorization() // Note - this is on the IMvcBuilder, not the service collection
    .AddJsonFormatters(options => options.ContractResolver = new CamelCasePropertyNamesContractResolver());
Run Code Online (Sandbox Code Playgroud)

  • 这也引起了我的注意(因为我正在使用`AddMvcCore`).调用`AddAuthorization()`添加了[`AuthorizationApplicationModelProvider`](https://github.com/aspnet/Mvc/blob/760c8f38678118734399c58c2dac981ea6e47046/src/Microsoft.AspNetCore.Mvc.Core/Internal/AuthorizationApplicationModelProvider.cs)对于控制器上的Authorize/AllowAnonymous并添加适当的策略. (5认同)

ade*_*lin 22

您还使用身份验证,它隐式包含cookie身份验证.您可能使用身份方案登录并导致身份验证成功.

如果不需要身份验证,则删除身份验证(如果您只想要jwt身份验证),否则请BearerAuthorize下面的属性指定scheme :

[Authorize(ActiveAuthenticationSchemes = "Bearer")]
Run Code Online (Sandbox Code Playgroud)


And*_*nca 8

对于那些甚至尝试过预览答案但没有解决问题的人,以下是我所解决的问题。

[Authorize(AuthenticationSchemes="Bearer")]
Run Code Online (Sandbox Code Playgroud)