为什么 jwt 身份验证在 ASP.NET Core Web API 中不起作用?

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

基本上我使用 ASP.NET Core Web API,当我向 Login 发送请求时控制器返回 Ok,它将刷新和访问令牌设置为仅 http cookie。

但是有一个问题:用户没有经过身份验证(我的意思是,即使我尝试转到[授权]路线,它也不起作用,或者尝试使用身份访问用户...,仍然不起作用] 由于某种原因,我手动检查了 jwt,并且 exp 日期、aud 和 issues 都设置良好,我只是不知道问题是什么。

在program.cs中,新的JwtBearerEvents甚至不向控制台打印任何内容。请帮助我。

******************this is a part of the service for the controller:

public async Task<bool> Login(LoginUserModel user)
{
   var identityUser = await _userManager.FindByNameAsync(user.UserName!);
   if (identityUser is null)
   {
       return false;
   }

   return await _userManager.CheckPasswordAsync(identityUser, user.Password!);
}
public string GenerateTokenString(LoginUserModel user)
{
   var tokenId = Guid.NewGuid().ToString(); // Unique identifier for each token

   var claims = new List<Claim>
   {
       new Claim(ClaimTypes.NameIdentifier, user.UserName !),
       new Claim(ClaimTypes.Role, "Admin"), // This should be dynamic based on actual user role
       new Claim("TokenId", tokenId) // Include the unique TokenId in the token
   };

   var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
   var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha512Signature);

   var tokenDescriptor = new SecurityTokenDescriptor
   {
       Subject = new ClaimsIdentity(claims),
       Expires = DateTime.UtcNow.AddMinutes(60), // Token validity period
       Issuer = _config["Jwt:Issuer"],
       Audience = _config["Jwt:Audience"],
       SigningCredentials = signingCredentials

   };

   var tokenHandler = new JwtSecurityTokenHandler();
   var token = tokenHandler.CreateToken(tokenDescriptor);

   return tokenHandler.WriteToken(token);
}
public async Task<string> GenerateRefreshToken(string userName)
{
   var user = await _userManager.FindByNameAsync(userName);
   if (user == null) return null!;

   // Create a new refresh token
   var refreshToken = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
   user.RefreshToken = refreshToken;
   user.RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(14); // Set refresh token validity

   await _userManager.UpdateAsync(user);

   return refreshToken;
}

***************************this is the program.cs:

using EasyLink.Server.Database.Context;
using EasyLink.Server.Identity;
using EasyLink.Server.Services.Auth;
using EasyLink.Server.Services.Categories;
using EasyLink.Server.Services.Stripe;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Stripe;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHttpClient();

// Configure DbContext.
builder.Services.AddDbContext<AuthDbContext>(options =>
   options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// Configure Identity.
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
   options.Password.RequiredLength = 8;
   options.Password.RequireLowercase = true;
   options.Password.RequireUppercase = true;
   options.Password.RequireDigit = true;
   options.Password.RequireNonAlphanumeric = false;
}).AddEntityFrameworkStores<AuthDbContext>()
 .AddDefaultTokenProviders();

// Configure JWT Authentication.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
   .AddJwtBearer(options =>
   {
       options.TokenValidationParameters = new TokenValidationParameters
       {
           ValidateIssuer = true,
           ValidateAudience = true,
           ValidateLifetime = true,
           ValidateIssuerSigningKey = true,
           ValidIssuer = builder.Configuration["Jwt:Issuer"],
           ValidAudience = builder.Configuration["Jwt:Audience"],
           IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)),
           ClockSkew = TimeSpan.Zero
       };
       options.Events = new JwtBearerEvents
       {
           OnAuthenticationFailed = context =>
           {
               Console.WriteLine("\n\n\n\n\n\n\nAuthentication failed: " + context.Exception.Message);
               return Task.CompletedTask;
           },
           OnTokenValidated = context =>
           {
               Console.WriteLine("\n\n\n\n\n\n\nToken validated successfully.");
               return Task.CompletedTask;
           },
           OnMessageReceived = context =>
           {
               Console.WriteLine("\n\n\n\nerror\n\n\n");
               if (context.Request.Cookies.ContainsKey("AccessToken"))
               {
                   context.Token = context.Request.Cookies["AccessToken"];
               }
               return Task.CompletedTask;
           }
       };
   });

// Additional services.
builder.Services.AddTransient<IAuthService, AuthService>();
builder.Services.AddScoped<IStripeService, StripeService>();
builder.Services.AddHttpClient("CategoryApiClient", client =>
{
   client.BaseAddress = new Uri("https://www.autovit.ro/api/");
   client.DefaultRequestHeaders.Add("Accept", "application/json");
});
builder.Services.AddScoped<ICategoriesService, CategoriesService>();
builder.Services.AddCors(options =>
{
   options.AddPolicy("AllowSpecificOrigin", builder =>
   {
       builder.WithOrigins("https://localhost:5173")
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials();
   });
});
StripeConfiguration.ApiKey = builder.Configuration["Stripe:Key"];

var app = builder.Build();

// Middleware pipeline configuration.
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseHsts();
app.UseCors("AllowSpecificOrigin");
if (app.Environment.IsDevelopment())
{
   app.UseSwagger();
   app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapFallbackToFile("/index.html");
app.Run();


***************************************this is a part of the authcontroller:
[HttpPost("Login")]
public async Task<IActionResult> Login([FromBody] LoginUserModel user)
{
   if (!ModelState.IsValid)
   {
       return BadRequest();
   }
   if (!await _authService.CheckPayment(user.UserName!))
   {
       return Unauthorized("Payment required.");
   }
   if (await _authService.Login(user))
   {
       var tokenString = _authService.GenerateTokenString(user);
       var refreshToken = await _authService.GenerateRefreshToken(user.UserName!);

       // Store access token and refresh token in HttpOnly cookies
       var cookieOptions = new CookieOptions
       {
           HttpOnly = true,
           Secure = true,
           SameSite = SameSiteMode.Strict,
           Expires = DateTime.UtcNow.AddMinutes(60)
       };

       Response.Cookies.Append("AccessToken", tokenString, cookieOptions);

       // Extend the cookie's expiry for refresh token since it should be valid longer than access token
       var refreshCookieOptions = new CookieOptions
       {
           HttpOnly = true,
           Secure = true,
           SameSite = SameSiteMode.Strict,
           Expires = DateTime.UtcNow.AddDays(14) // Refresh token validity
       };
       Response.Cookies.Append("RefreshToken", refreshToken, refreshCookieOptions);

       return Ok(new { message = "Login successful", accessToken = tokenString, refreshToken = refreshToken });
   }

   return Forbid("Invalid credentials.");
}


       [HttpGet("verify")]
       public IActionResult Verify()
       {
           var isAuthenticated = User.Identity!.IsAuthenticated;

           return Ok(new { isAuthenticated });
       }

我正在尝试登录用户... 基本上登录返回正常,但它仍然无法进行身份验证,我尝试了 [Authorize] 路由,并尝试 User.Identity!.IsAuthenticated;并且仍然返回 false,用户也很好地存储在数据库中..

c# .net authentication jwt asp.net-core-webapi
1个回答
0
投票

好吧,所以我自己发现了问题,问题是我没有设置好方案,这就是你应该修改的地方:

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
 ...
});
app.Use(async (context, next) =>
{
    var token = context.Request.Cookies["AccessToken"];
    if (!string.IsNullOrEmpty(token))
    {
        context.Request.Headers.Append("Authorization", $"Bearer {token}");
        Console.WriteLine("Token appended to header: " + token);
    }
    else
    {
        Console.WriteLine("No token found in cookies");
    }
    await next();
});

有趣的事实,当我在前端获取有效电子邮件的错误密码时,我发现了问题:)))

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