ASP.NET核心API始终返回401,但包含承载令牌

人气:621 发布:2022-10-16 标签: c# jwt asp.net-core-webapi

问题描述

我有一个ASP.NETCore Web API,并且我出于授权目的生成了一个JWT令牌,但每当我向带有承载令牌标头的邮递员发出请求时,我都会收到401未经授权的请求。当我从我的前端尝试使用API时,情况也是如此。取消授权后,一切正常

已尝试将标题中的授权更改为

[Authorize(AuthenticationSchemes = "Bearer")]

还访问了jwt.io以确保JWT令牌有效。

生成JWT令牌的函数

public User AuthenticateAdmin(string username, string password) 
{
    var user = _context.User
        .FirstOrDefault(x => x.UserName == username 
            && x.Password == password);

    //return null if user is not found 
    if (user == null) return null;

    //authentication successful so generate jwt token
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
    var tokenDescriptor = new SecurityTokenDescriptor 
    {
        Subject = new ClaimsIdentity(new Claim[] 
        {
            new Claim(ClaimTypes.Name, user.Id.ToString()),
            new Claim(ClaimTypes.Role, user.Role)
        }),
        Expires = DateTime.UtcNow.AddDays(7),
        SigningCredentials = 
            new SigningCredentials(
                new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };
    
    var token = tokenHandler.CreateToken(tokenDescriptor);
    user.Token = tokenHandler.WriteToken(token);
    
    user.Password = null;
    return user;
}

启动:

public class Startup 
{
    public Startup(IConfiguration configuration) 
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration 
    {
        get;
    }

    public void ConfigureServices(IServiceCollection services) 
    {
        services.Configure<AuthMessengerOptions>(Configuration);
        
        var connection = @"Host=localhost;Database=PayArenaMock;Username=postgres;Password=tim";
       
        services.AddDbContext<PayArenaMockContext>(
           options => options.UseNpgsql(connection));
        
        services.AddTransient<IEmailSender, EmailSender>();

        // services.AddAuthorization(auth =>
        // {
        //     auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
        //             .AddAuthenticationSchemes(
        //                 JwtBearerDefaults.AuthenticationScheme)
        //       .RequireAuthenticatedUser().Build());
        // });
        
        services.AddCors();
        
        // Note - this is on the IMvcBuilder, not the service collection
        // services.AddMvcCore()
        //     .AddAuthorization() 
        //     .AddJsonFormatters(options => options.ContractResolver = 
        //         new CamelCasePropertyNamesContractResolver());
        
        // services.AddMvcCore()
        //     .AddJsonFormatters(options => 
        //         options.ContractResolver = new CamelCasePropertyNamesContractResolver());
                
        services.AddMvc()
            .SetCompatibilityVersion(
                    CompatibilityVersion.Version_2_2);
        
        //configure strongly typed settings objects
        var appSettingsSection = 
            Configuration.GetSection("AppSettings");
            
        services.Configure<AppSettings>(appSettingsSection);
        
        //configure JWT authentication
        var appSettings = appSettingsSection.Get<AppSettings>();
        
        var key = Encoding.ASCII.GetBytes(appSettings.Secret);
        
        services.AddAuthentication(x => 
        {
            x.DefaultAuthenticateScheme = 
                JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = 
                JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x => 
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters 
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });

        services.AddScoped<IUserService,UserService>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env) 
    {
        if (env.IsDevelopment()) 
        {
            app.UseDeveloperExceptionPage();
        } 
        else 
        {
            app.UseHsts();
        }
        
        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader());
            
        app.UseAuthentication();
        app.UseHttpsRedirection();
        app.UseMvc();
    }
    
}

控制器:

//[Authorize(AuthenticationSchemes = "Bearer")]
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class BusinessListingsController: ControllerBase 
{
    private readonly PayArenaMockContext _context;

    public BusinessListingsController(PayArenaMockContext context)
    {
        _context = context;
    }

    // GET: api/BusinessListings
    [HttpGet]
    //[AllowAnonymous]
    //[Authorize(Roles = Role.Admin)]
    public async Task<ActionResult<IEnumerable<BusinessListing>>> 
        GetBusinessListing() 
    {

        //var businesslisting = _context.BusinessListing
        //    .Include(b => b.CategoryNameNav);
      
        var businesslisting = await _context
            .BusinessListing
            .ToListAsync();
            
        return Ok(businesslisting);
    }
    
}

推荐答案

我遇到了同样的问题,但在移动后

app.UseAuthentication();

至第

行之前
app.UseAuthorization();

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ..
    app.UseAuthentication();
    ..
    app.UseAuthorization();
    ...
}

成功了。

504