【问题标题】:Asp.Net Web Api JWT Authorization With Identity Always Getting 401带有身份的 Asp.Net Web Api JWT 授权总是得到 401
【发布时间】:2021-04-24 11:26:34
【问题描述】:

我正在使用 Asp.Net Core 5,以及带有 EFcore 的 Asp.Net Identity。我已经关注了许多视频教程的部分内容、在 SO 上发布的建议和 this 非常有用的文章,以使我的项目达到我至少获得 401 的程度。我现在的问题是我不明白为什么我会得到 401。我已经用我在 jwt.io 上的秘密验证了我的令牌,一切都告诉我它应该可以工作,但事实并非如此。我完全不知所措。废话不多说,言归正传。

我的创业班。注意:在 OnMessageReceived 事件上下文中。Token 为 null,直到我使用授权标头设置它。

//imports

namespace auto_highlighter_iam
{
    public class Startup
    {

        private readonly IConfiguration _config;
        private readonly IWebHostEnvironment _env;
        public Startup(IConfiguration config, IWebHostEnvironment env)
        {
            _config = config;
            _env = env;
        }

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

            services.AddDbContext<DataContext>(options =>
            {
                options.UseNpgsql(_config.GetConnectionString("AutoHighlighterIAMDev"));
            });

            IdentityBuilder iBuilder = services.AddIdentityCore<IdentityUser>(options =>
            {
                options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._ ";
                options.Password.RequiredLength = 12;
                options.Password.RequireDigit = false;
                options.Password.RequireLowercase = false;
                options.Password.RequireUppercase = false;
                options.Password.RequireNonAlphanumeric = false;
                options.User.RequireUniqueEmail = true;
                //options.SignIn.RequireConfirmedEmail = true;
            });
            iBuilder = new IdentityBuilder(iBuilder.UserType, typeof(IdentityRole), iBuilder.Services)
                .AddEntityFrameworkStores<DataContext>()
                .AddRoleManager<RoleManager<IdentityRole>>()
                .AddSignInManager<SignInManager<IdentityUser>>();


            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(config =>
           {
               config.Events = new JwtBearerEvents()
               {
                   OnMessageReceived = context =>
                   {
                       // Interesting note here. before this next line context.Token is null, but the authorization header has the jwt
                       context.Token = context.Request.Headers[HeaderNames.Authorization];
                       // Although the previous line successfully set context.Token to the jwt still getting 401's

                       return Task.CompletedTask;
                   }
               };
               config.RequireHttpsMetadata = !_env.IsDevelopment();
               config.TokenValidationParameters = new TokenValidationParameters
               {
                   ValidateIssuerSigningKey = true, //tried as false
                   IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JWT:Secret"])),
                   ValidateIssuer = true, //tried as false
                   ValidIssuer = _config["JWT:Iss"],
                   ValidateAudience = true, //tried as false
                   ValidAudience = _config["JWT:Aud"]
               };
           });

            services.AddAuthorization();

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "auto_highlighter_iam", Version = "v1" });

                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    In = ParameterLocation.Header,
                    Description = "Insert JWT with Bearer into field",
                    Name = "Authorization",
                    Type = SecuritySchemeType.ApiKey
                });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        Array.Empty<string>()
                    }
                });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext)
        {
            dataContext.Database.Migrate();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "auto_highlighter_iam v1"));
            }

            app.UseExceptionHandler("/exception");

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseAuthentication();

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

我的授权控制器。有三个端点。两个用于测试我拥有的角色,一个用于测试任何有效的 jwt。它们都返回 401。

// imports

namespace auto_highlighter_iam.Controllers
{
    [ApiController]
    [Route("/api-v1/[controller]")]
    public class AuthorizationController : ControllerBase
    {
        [HttpGet("[action]")]
        [Authorize(Roles = "SUPERADMIN")]
        public IActionResult TestSuperAdmin()
        {
            return Ok();
        }

        [HttpGet("[action]")]
        [Authorize(Roles = "DEFAULT")]
        public IActionResult TestDefault()
        {
            return Ok();
        }

        [HttpGet("[action]")]
        [Authorize]
        public IActionResult TestAny()
        {
            return Ok();
        }
    }
}

我正在测试的 JWT(假设令牌没有过期,我一直在确保它有效)

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJWSUVXIjoiRmFsc2UiLCJFRElUIjoiRmFsc2UiLCJERUxFVEUiOiJGYWxzZSIsIkNSRUFURSI6IkZhbHNlIiwicm9sZXMiOiJERUZBVUxUIiwibmJmIjoxNjExMTIxNTI1LCJleHAiOjE2MTExMjUxMjUsImlzcyI6ImF1dG8taGlnaGxpZ2h0ZXItaWFtIiwiYXVkIjoiYXV0by1oaWdobGlnaHRlci1mcm9udC1lbmQifQ.jnbW552pr7kylc82-4FmJJMmaeu7LQ7L48M5cdnSzuMsA1yRuts9sXUQ2_ok41SqX8mFpi7yreJJXGlE6qC1vA

我发送的请求

curl --location --request GET 'http://localhost:5000/api-v1/Authorization/TestAny' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJWSUVXIjoiRmFsc2UiLCJFRElUIjoiRmFsc2UiLCJERUxFVEUiOiJGYWxzZSIsIkNSRUFURSI6IkZhbHNlIiwicm9sZXMiOiJERUZBVUxUIiwibmJmIjoxNjExMTIwMDkzLCJleHAiOjE2MTExMjM2OTMsImlzcyI6ImF1dG8taGlnaGxpZ2h0ZXItaWFtIiwiYXVkIjoiYXV0by1oaWdobGlnaHRlci1mcm9udC1lbmQifQ.zOsNADvKGx1FYkzKLX4K53Y185dHFiM408aAjinQUQrVWQ_spXClozOAvp2glgiQkM0IwkDneB4Q_JCpQfet1g'

如果我遗漏了什么,我会尽快提供更多信息。

【问题讨论】:

  • 嗨@Ryan Callahan,关于这个案例有什么更新吗?

标签: c# asp.net-core jwt asp.net-identity asp.net-roles


【解决方案1】:

你需要把你的中间件:

app.UseAuthentication();

在你的app.UseAuthorization();之前

像这样:

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

更新:

并且您需要将您的请求更改为(删除Bearer):

curl --location --request GET 'http://localhost:5000/api-v1/Authorization/TestAny' \
--header 'Authorization: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJWSUVXIjoiRmFsc2UiLCJFRElUIjoiRmFsc2UiLCJERUxFVEUiOiJGYWxzZSIsIkNSRUFURSI6IkZhbHNlIiwicm9sZXMiOiJERUZBVUxUIiwibmJmIjoxNjExMTIwMDkzLCJleHAiOjE2MTExMjM2OTMsImlzcyI6ImF1dG8taGlnaGxpZ2h0ZXItaWFtIiwiYXVkIjoiYXV0by1oaWdobGlnaHRlci1mcm9udC1lbmQifQ.zOsNADvKGx1FYkzKLX4K53Y185dHFiM408aAjinQUQrVWQ_spXClozOAvp2glgiQkM0IwkDneB4Q_JCpQfet1g'

【讨论】:

  • 改变了我的配置方法,但没有奏效。真希望就是这样。
  • 嗨@Ryan Callahan,你可以看到我的更新答案。
  • 很抱歉回复晚了,但这最终成为了问题。不过,这让我感到惊讶,因为我认为 Bearer auth 需要 Bearer 在它前面。谢谢!
猜你喜欢
  • 2018-01-09
  • 2020-09-10
  • 1970-01-01
  • 2021-02-16
  • 2016-12-14
  • 1970-01-01
  • 2013-02-26
  • 2021-09-28
  • 2012-09-10
相关资源
最近更新 更多