ASP.NET Core 8 Web API:JWT 令牌始终无效

问题描述 投票:0回答:1

在 ASP.NET Core 8 Web API 上通过 JWT 进行身份验证时,总是抛出此错误:

承载错误=“invalid_token”

无论我做什么。

我已经通过

jwt.io
检查了令牌,一切看起来都很正常。

我还检查了 Chrome 网络选项卡,一切看起来都很正常。

我完全不知道,因为我遵循了 YouTube 教程,一切都正常,而且我对 ASP.NET Core 还很陌生。

仓库:https://github.com/LarsSK06/Home-Server.Backend/tree/dev

Program.cs

using HomeServer.Data;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using Microsoft.IdentityModel.Tokens;
using System.Text;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen(options => {
    options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme{
        In = ParameterLocation.Header,
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey
    });
    
    options.OperationFilter<SecurityRequirementsOperationFilter>();
});

builder.Services.AddSingleton<MongoDBService>();

builder.Services.AddCors(options => {
    options.AddDefaultPolicy(
        policy =>
            policy.WithOrigins("http://localhost:3000")
    );
});

builder.Services.AddAuthentication().AddJwtBearer(options => {
    options.TokenValidationParameters = new TokenValidationParameters{
        ValidateIssuerSigningKey = true,
        ValidateAudience = false,
        ValidateIssuer = false,
        IssuerSigningKey = new SymmetricSecurityKey(
            Encoding.UTF8.GetBytes(
                builder.Configuration.GetSection("AppSettings:Token").Value!
            )
        )
    };
});

WebApplication app = builder.Build();

if(app.Environment.IsDevelopment()){
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

appsettings.json

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Warning"
        }
    },
    "AllowedHosts": "*",
    "ConnectionStrings": {
        "DatabaseConnection": "mongodb://localhost:27017/dev"
    },
    "AppSettings": {
        "Token": "jdiwlpmfpn210dff1kg92wagwagagrgrgrddgdgdrdrrggrdwdwafawfwafwafawfafawfffwwf"
    }
}

Users.cs
Users/
端点

的API控制器
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using HomeServer.Models;
using HomeServer.Data;
using HomeServer.Utilities;
using Microsoft.AspNetCore.Authorization;

namespace HomeServer.Controllers;

[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
    private readonly IMongoCollection<User>? _users;
    private readonly IConfiguration _config;

    public UsersController(MongoDBService mongoDBService, IConfiguration configuration)
    {
        _users = mongoDBService.Database?.GetCollection<User>("users");
        _config = configuration;
    }

    [HttpGet, Authorize]
    public async Task<ActionResult<IEnumerable<PublicUser>>> GetUsers()
    {
        if (_users is null)
            return NotFound();

        FilterDefinition<User>? filter = FilterDefinition<User>.Empty;
        IAsyncCursor<User>? cursor = await _users.FindAsync(filter);
        List<User>? users = await cursor.ToListAsync();
        List<PublicUser> publicUsers = [];

        foreach(User i in users)
            publicUsers.Add(i.ToPublic());

        return Ok(publicUsers);
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<PublicUser>> GetUser(int id)
    {
        if (_users is null)
            return NotFound();
        
        FilterDefinition<User>? filter = Builders<User>.Filter.Eq(i => i.Id, id);
        IAsyncCursor<User>? cursor = await _users.FindAsync(filter);
        User? first = await cursor.FirstOrDefaultAsync();

        if (first is null)
            return NotFound();

        return first.ToPublic();
    }

    [HttpPost]
    public async Task<ActionResult<PublicUser>> CreateUser(MutableUser data)
    {
        if (_users is null)
            return NotFound();
        
        FilterDefinition<User> conflictedUsersFilter =
            Builders<User>.Filter.Eq(i => i.Email, data.Email);

        IAsyncCursor<User>? conflictedUsersCursor =
            await _users.FindAsync(conflictedUsersFilter);

        List<User> conflictedUsers = await conflictedUsersCursor.ToListAsync();

        if (conflictedUsers.Count > 0)
            return Conflict();

        User user = new()
                    {
                        Id = Generator.GetEpoch(),
                        Name = data.Name,
                        Password = BCrypt.Net.BCrypt.HashPassword(data.Password, 15),
                        Email = data.Email,
                        Admin = data.Email.Equals("[email protected]")
                    };

        await _users.InsertOneAsync(user);

        return CreatedAtAction(
            nameof(GetUser),
            new { id = user.Id },
            user.ToPublic()
        );
    }

    [HttpPost("LogIn")]
    public async Task<ActionResult<PublicUser>> LogIn(Credentials credentials)
    {
        if (_users is null)
            return NotFound();

        FilterDefinition<User>? filter = Builders<User>.Filter.Eq(i => i.Email, credentials.Email);
        IAsyncCursor<User>? users = await _users.FindAsync(filter);
        User? user = await users.FirstOrDefaultAsync();

        if (user is null)
            return BadRequest();

        if (!BCrypt.Net.BCrypt.Verify(credentials.Password, user.Password))
            return Unauthorized();
        
        string token = JWT.CreateToken(_config, user.ToPublic());
        
        return Ok(token);
    }
}

public class Credentials
{
    public required string Email { get; set; }
    public required string Password { get; set; }
}

User.cs
(MongoDB 模型)

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace HomeServer.Models;

public class User
{
    [BsonId]
    [BsonElement("_id"), BsonRepresentation(BsonType.ObjectId)]
    public string? MongoId { get; set; }

    [BsonElement("id"), BsonRepresentation(BsonType.Int32)]
    public required int Id { get; set; }

    [BsonElement("name"), BsonRepresentation(BsonType.String)]
    public required string Name { get; set; }

    [BsonElement("password"), BsonRepresentation(BsonType.String)]
    public required string Password { get; set; }

    [BsonElement("email"), BsonRepresentation(BsonType.String)]
    public required string Email { get; set; }

    [BsonElement("admin"), BsonRepresentation(BsonType.Boolean)]
    public required bool Admin { get; set; }

    public PublicUser ToPublic()
    {
        return new PublicUser
                   {
                       Id = Id,
                       Name = Name,
                       Email = Email,
                       Admin = Admin
                   };
    }

    public MutableUser ToMutable()
    {
        return new MutableUser
                   {
                       Name = Name,
                       Password = Password,
                       Email = Email
                   };
    }
}

public class PublicUser
{
    public required int Id { get; set; }
    public required string Name { get; set; }
    public required string Email { get; set; }
    public required bool Admin { get; set; }
}

public class MutableUser
{
    public required string Name { get; set; }
    public required string Password { get; set; }
    public required string Email { get; set; }
}

JWT.cs
CreateToken
功能的位置)

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using HomeServer.Models;
using Microsoft.IdentityModel.Tokens;

namespace HomeServer.Utilities;

public struct JWT
{
    public static string CreateToken(IConfiguration config, PublicUser user)
    {
        List<Claim> claims = new List<Claim>
                                 { new Claim(ClaimTypes.Email, user.Email) };

        SymmetricSecurityKey key =
            new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
                config.GetSection("AppSettings:Token").Value!)
            );

        SigningCredentials credentials =
            new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

        JwtSecurityToken token = new JwtSecurityToken(
            claims: claims,
            expires: DateTime.Now.AddHours(12),
            signingCredentials: credentials
        );

        string jwt = new JwtSecurityTokenHandler().WriteToken(token);

        return jwt;
    }
}

可以在存储库中看到提交,但除此之外,我已经尝试了大多数 YouTube 教程的详细信息,但没有成功。

我尝试过向

AddSwaggerGen
AddAuthentication
AddJwtBearer
添加不同的选项,但我无法弄清楚。

c# mongodb asp.net-core-webapi .net-8.0 asp.net-core-8
1个回答
0
投票

通过以下设置,它似乎可以工作:

builder.Services.AddAuthentication().AddJwtBearer(options =>
{
    options.UseSecurityTokenValidators = true; // use JwtSecurityToken
    options.TokenValidationParameters = new TokenValidationParameters{
        ValidateIssuerSigningKey = true,
        ValidateAudience = false,
        ValidateIssuer = false,
        RequireExpirationTime = false, // for some reason "exp" field from JWT is not recognized
        IssuerSigningKey = new SymmetricSecurityKey(
            Encoding.UTF8.GetBytes(
                builder.Configuration.GetSection("AppSettings:Token").Value!
            )
        )
    };
});
© www.soinside.com 2019 - 2024. All rights reserved.