ASP.Net Core 3 API 总是返回 401-JwtBearer

lea*_*nus 1 .net c# api core jwt

我有一个 ASP .NET Core web api,我生成了一个 JWT 令牌用于授权目的,但是每当我发出请求时,我都会收到401 - Unauthorized

操作顺序:

     1. GET for token
     2. GET for user <-- 401
Run Code Online (Sandbox Code Playgroud)

我在 jwt.io 上检查了我的令牌,它是正确的。 当我删除[Authorize] attrivute 时一切正常

启动文件

   public void ConfigureServices(IServiceCollection services)
        {
            IdentityModelEventSource.ShowPII = true;
            var appSettingsSection = Configuration.GetSection("Jwt");
            services.Configure<JwtSettings>(appSettingsSection);
            var appSettings = appSettingsSection.Get<JwtSettings>();
            services.AddControllers();
            services.AddOptions();

            services.AddAuthentication(x => 
            {
                x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;

            })
            .AddJwtBearer(x=>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    ValidateIssuer = true,
                    ValidateLifetime = true,
                    ValidAudience = appSettings.Issuer,
                    ValidIssuer = appSettings.Issuer,
                    ValidateAudience = false,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.Key))
                };

            }
            );
        }



  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseRouting();
            app.UseHttpsRedirection();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();

            });
        }
Run Code Online (Sandbox Code Playgroud)

CreateToken 方法

 public JwtDto CreateToken(string email, string role)
        {
            var now = DateTime.UtcNow;
            var claims = new Claim[]
            {
                new Claim(JwtRegisteredClaimNames.Sub,email),
                new Claim(ClaimTypes.Role, role),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat,now.ToTimestamp().ToString(),ClaimValueTypes.Integer64)
            };


            var expires = now.AddMinutes(360);
            var singingCredentails = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_settings.Key)),SecurityAlgorithms.HmacSha256);

            var jwt = new JwtSecurityToken(
                issuer: _settings.Issuer,
                claims: claims,
                notBefore: now,
                expires: expires,
                signingCredentials: singingCredentails
            );
            var token = new JwtSecurityTokenHandler().WriteToken(jwt);

            return new JwtDto
            {
                Token = token,
                Expiry = expires.ToTimestamp()
            };
        }
Run Code Online (Sandbox Code Playgroud)

获取令牌 - API

[HttpGet]
[Route("token")]
public IActionResult GetToken()
{
    var token = _jwtHandler.CreateToken("test", "user");
    return Json(token);
}
Run Code Online (Sandbox Code Playgroud)

GetUser - API <---------- 401 错误

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    [HttpGet("{email}")]
    public async Task<UserDto> Get(string email)
    {
      return  await _userService.GetUserAsync(email);
    }
Run Code Online (Sandbox Code Playgroud)

令牌请求

Dom*_*nik 5

我遇到了完全相同的问题,并认为问题出在 Startup.cs 中的 Configure() 方法中。您有正确的 UseAuthentication() 和 UseAuthorization() 调用,顺序正确,这很重要,也是我发现的问题。因此,对您而言,我认为问题在于缺少 UseCors() 调用。我的工作启动课程如下:

public class Startup
{
    private bool _isDevelopmentEnvironment = true;
    public IConfiguration configuration { get; }

    public Startup(IConfiguration configuration)
    {
        this.configuration = configuration;
    }

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

        // Retrieve App Settings:
        var appSettingsSection = configuration.GetSection("AppSettings");
        services.Configure<AppSettings>(appSettingsSection);
        var appSettings = appSettingsSection.Get<AppSettings>();

        // Configure JWT:
        var key = Encoding.ASCII.GetBytes(appSettings.JwtSharedSecret);
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = !_isDevelopmentEnvironment;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = appSettings.JwtValidateIssuer,
                ValidateAudience = appSettings.JwtValidateAudience,
                ValidateLifetime = appSettings.JwtValidateLifetime,
                ClockSkew = TimeSpan.Zero
            };
        });

        services.AddScoped<IUserRepository, UserRepository>();
        services.AddScoped<IUserService, UserService>();
        services.AddScoped<IHydrator<User, UserModel>, UserModelHydrator>();
    }

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

        app.UseHttpsRedirection();

        app.UseRouting();

        // TODO: Adjust CORS settings appropriately
        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader());

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

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我还确认令牌生成代码和 Startup.cs 代码使用应用程序设置中的相同密钥,我看不出你是如何在 CreateToken() 方法中获得它的,但我假设它来自相同的设置文件。希望这可以帮助!