c# - Web API 核心 JWT 身份验证不起作用

标签 c# .net asp.net-core webapi

我是在 .NET 中编写 Web API 的新手。我编写了这个 API,它正常工作,但后来我添加了 JWT 身份验证,现在当我提供正确的用户名和密码时,我会得到一个身份验证承载 token ,我将其添加到 swagger UI 但现在当我尝试访问时任何其他端点我都会收到此 401 未经授权状态。我无法理解为什么。我也用 Postman 尝试过,但得到了相同的响应。

这是我的 Program.cs

using System.Text;
using Comply_Api_DotNet.Database;
using Comply_Api_DotNet.Repository;
using Comply_Api_DotNet.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddScoped<IUsersDb, UsersDb>();
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = @"Please provide authorization token to access restricted features.",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });

    c.AddSecurityRequirement(new OpenApiSecurityRequirement()
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                },

                Scheme = "oauth2",
                Name = "Bearer",
                In = ParameterLocation.Header,
            },
            new List<string>()
        }
    });
});
// ADD JWT Authentication
builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    var key = Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"]);
    o.SaveToken = true;
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        ValidAudience = builder.Configuration["JWT:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(key)
    };
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

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

app.MapControllers();

app.Run();  

她是我的 Controller 。

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
    private readonly IAuthenticationService _authenticationService;
    private readonly IUsersDb _usersDb;

    public UsersController(IAuthenticationService authenticationService, IUsersDb usersDb)
    {
        _authenticationService = authenticationService;
        _usersDb = usersDb;
    }

    [AllowAnonymous]
    [HttpPost]
    [Route("authenticate")]
    public IActionResult Authenticate(User user)
    {
        var token = _authenticationService.Authenticate(user);

        if (token == null)
        {
            return Unauthorized();
        }

        return Ok(token);
    }


    // GET api/<UsersController>/5
    [HttpGet]
    public IEnumerable<User> Get(long id)
    {
        var usersFound = _usersDb.GetAllUsers(id);
        return usersFound;
    }

    // POST api/<UsersController>
    [HttpPost]
    public User Post([FromBody] User user)
    {
        var userAdded = _usersDb.AddNewUser(user);
        return userAdded;
    }

    // PUT api/<UsersController>/5
    [HttpPut("{id:long}")]
    public void Put(long id, [FromBody] User user)
    {
        throw new NotImplementedException();
    }


    [HttpDelete("{id:long}")]
    public bool Delete(long id)
    {
        return _usersDb.DeleteUser(id);
    }
} // end of class  

appsettings.Json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "JWT": {
    "Key": "fc746b61cde4f6665d3f9791446cd5395661860c0075a905ed9810b7391af467",
    "Issuer": "Comply",
    "Audience": "comply"
  } 
}

更新:身份验证服务

public class AuthenticationService : IAuthenticationService
{
    private readonly IConfiguration _configuration;
    private readonly IUsersDb _usersDb;

    public AuthenticationService(IConfiguration configuration, IUsersDb usersDb)
    {
        _configuration = configuration;
        _usersDb = usersDb;
    }

    public AuthenticationToken? Authenticate(User user)
    {
        var foundUser = _usersDb.GetAllUsers(0)
            .FirstOrDefault(x => x.Name == user.Name && x.Password == user.Password);
        if (foundUser == null)
        {
            return null;
        }

        //If user found then generate JWT
        return CreateAuthenticationToken(foundUser);
    }

    private AuthenticationToken CreateAuthenticationToken(User user)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var tokenKey = Encoding.UTF8.GetBytes(_configuration["JWT:Key"]);

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new(ClaimTypes.Name, user.Name),
            }),

            Expires = DateTime.UtcNow.AddMinutes(10),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tokenKey),
                SecurityAlgorithms.HmacSha256Signature),
            Issuer = _configuration["JWT:Issuer"],
            Audience = _configuration["JWT:Audience"],
        };

        var token = tokenHandler.CreateToken(tokenDescriptor);

        return new AuthenticationToken()
        {
            Token = tokenHandler.WriteToken(token),
        };
    }
} //end of class

最佳答案

问题出在这里Type = SecuritySchemeType.ApiKey,您将安全方案类型指定为apiKey。您需要将其替换为 Type = SecuritySchemeType.Http,。因此,您的 OpenApiSecurityScheme 现在应该如下所示。

c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
    Description = @"Please provide authorization token to access restricted features.",
    Name = "Authorization",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.Http,
    Scheme = "Bearer",
    BearerFormat = "JWT",
});

关于c# - Web API 核心 JWT 身份验证不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72275178/

相关文章:

c# - Thread.Sleep 是在 C# 中实现我自己的 Timer 的正确方法吗?

c# - 自定义中间件导致 Blazor 服务器端页面停止工作

c# - startup.cs的Configure方法中如何使用ConfigurationBinder

c# - 编译器常量、优化和性能

原始类型的 C# 重载运算符

c# - 在泛型类型的构造函数中使用 C# params 关键字

asp.net-core - ASP.NET Core 托管环境变量被忽略

c# - 另一个游戏对象背后的粒子系统渲染

c# - 如何在 where 子句中使用 LINQ Except()

c# - 为什么 IPAddress 构造函数采用 Int64 而不是 UInt32?