ASP.NET Core 8 基于默认身份令牌的身份验证不起作用 - 404 未找到错误

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

我正在尝试在 .NET core 8 Web API 应用程序中探索基于身份令牌的身份验证。我能够注册用户、生成和存储令牌。但是,当我尝试访问授权 api 时,它失败了,重定向到 /Account/login 端点。请注意,我已为我自己的 API/操作添加了 [Authorize] attr。根据我的分析,它重定向到 /Account/Login 因为 API 没有这个端点,因此它抛出 404 而不是 401。我担心的是为什么它甚至无法进行身份验证。

我尝试了多种配置来使其工作,但没有一个有帮助, 请在此指导。

注意B 我成功地能够使用 Jwt 令牌,我想使用默认身份进行令牌管理而不是 JWT。参考了docs,但我在某处遗漏了它。

代码: 程序

var builder = WebApplication.CreateBuilder(args);  
builder.Services.AddDbContext<ApplicationDbContext>(
                options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))
            );
    builder.Services.AddDatabaseDeveloperPageExceptionFilter();
    
    builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.SignIn.RequireConfirmedAccount = false;
        })
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders(); // Ensures to use default AspNet token providers
    
    builder.Services.AddAuthentication()
        .AddBearerToken(IdentityConstants.BearerScheme); // tried few options but same error
    builder.Services.AddAuthorization();
    
    /* This is working as expected
    var issuer = builder.Configuration.GetSection("Jwt:Issuer").Get<string>();
    var audience = builder.Configuration.GetSection("Jwt:Audience").Get<string>();
    var secretKey = builder.Configuration.GetSection("Jwt:SecretKey").Get<string>();
    
    builder.Services.AddAuthentication(
        options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(
        options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = issuer,
                ValidAudience = audience,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey))
            };
        });
    */
    
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    builder.Services.AddScoped<IJwtService, JwtService>();
    builder.Services.AddScoped<IAspTokenService, AspTokenService>();
    builder.Services.AddControllers();
    
    var app = builder.Build();
    
    using (var scope = app.Services.CreateScope())
    {
        var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        db.Database.Migrate();
    }
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    
    app.Run();

控制器:

    [HttpPost("register")]
[AllowAnonymous]
public async Task<ActionResult> Register([FromBody] RegisterModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var appUser = new ApplicationUser() { UserName = model.UserId, Email = model.Email, NewAddress = model.Address };
    var result = await _userManager.CreateAsync(appUser, model.Password);
    if (result.Succeeded)
    {
        //var token = _jwtService.GenerateToken(model.UserId);
        var token = await _aspTokenService.GenerateAndStoreTokenAsync(appUser.UserName);
        return Ok(token);
    }

    return BadRequest(result.Errors);
}

[HttpPost("login")]
[AllowAnonymous]
public async Task<ActionResult> Login([FromBody] LoginModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var user = await _userManager.FindByNameAsync(model.UserId);
    if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
    {
        //var token = _jwtService.GenerateToken(user.UserName);
        var token = await _aspTokenService.GenerateAndStoreTokenAsync(user.UserName);
        return Ok(token);
    }

    return Unauthorized();
}

[HttpGet("securedata")]
[Authorize]
public ActionResult GetSecureData()
{
    string token = string.Empty;
    var usersCliams = User.Identity as ClaimsIdentity;
    foreach (var claim in usersCliams?.Claims)
    {
        if ("Id".Equals(claim.Type))
        {
            token = claim.Value.ToString();
            break;
        }
    }
    return Ok(new { Message = $"Id {token}" });
}

服务

private UserManager<ApplicationUser> _userManager;

public AspTokenService(UserManager<ApplicationUser> userManager)
{
    _userManager = userManager;
}

public async Task<TokenDto> GenerateAndStoreTokenAsync(string username)
{
    if (string.IsNullOrEmpty(username))
    {
        return null;
    }

    var user = await _userManager.FindByNameAsync(username);
    if (user == null)
    {
        return null;
    }

    var token = await _userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, user.Id);
    await _userManager.SetAuthenticationTokenAsync(user, TokenOptions.DefaultProvider, user.Id, token);
    return new TokenDto { Token = token };
}

public async Task<TokenDto> GetTokenAsync(string username)
{
    if (string.IsNullOrEmpty(username))
    {
        return null;
    }

    var user = await _userManager.FindByNameAsync(username);
    if (user == null)
    {
        return null;
    }

    var token = await _userManager.GetAuthenticationTokenAsync(user, TokenOptions.DefaultProvider, user.Id);
    return new TokenDto { Token = token };
}

其他

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }
}
 public class ApplicationUser : IdentityUser
 {
     public string? NewAddress { get; set; }
 }

数据库表映射 - 检查用户Manu123456,忽略其他两个

c# authentication asp.net-core-identity asp.net-core-8
1个回答
0
投票

在 .net 8 中,现在有用于 asp.net 身份的内置 jwt 端点。
安装包

Microsoft.AspNetCore.Identity.EntityFrameworkCore

不要使用
AddIdentity
,尝试使用以下代码

builder.Services.AddIdentityCore<IdentityUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager()
    .AddRoleManager<RoleManager<IdentityRole>>()
    .AddDefaultTokenProviders();
...
app.MapIdentityApi<IdentityUser>();

参考:https://andrewlock.net/exploring-the-dotnet-8-preview-introducing-the-identity-api-endpoints/

© www.soinside.com 2019 - 2024. All rights reserved.