401 Несанкционированная ошибка с аутентификацией JWT в приложении .NET 8 и Vue.jsC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 401 Несанкционированная ошибка с аутентификацией JWT в приложении .NET 8 и Vue.js

Сообщение Anonymous »

Я создаю небольшое приложение, использующее .NET 8 для серверной части и Vue для внешней.
На данный момент у меня есть функция входа в систему. Как только пользователь входит в систему, его данные загружаются на «Главный» экран.
Я пытаюсь реализовать вход с помощью JWT для дополнительной безопасности и узнать, как это сделать, поскольку это хороший способ. практикуюсь в более крупных приложениях, но постоянно сталкиваюсь с ошибкой 401 Unauthorized и не могу ее устранить.
В моем файле appsettings.json есть необходимые параметры для JWT:

Код: Выделить всё

"Jwt": {
"Key": "8D9E3B5F7C2A4E9D1F3C6A7E9B2D4C8F",
"Issuer": "http://localhost:5251",
"Audience": "http://localhost:8080"
}
Этим ключом я подписываю токен, сгенерированный при входе пользователя в систему:

Код: Выделить всё

// Login method
[HttpPost("login")]
public async Task Login([FromBody] LoginDto loginDto)
{
var user = await _context.Users.FirstOrDefaultAsync(u => u.UserName ==
loginDto.UserName);

if (user == null || !BCrypt.Net.BCrypt.Verify(loginDto.Password, user.Password))
{
return Unauthorized(new { message = "Invalid username or password." });
}

// Create the JWT token
var tokenHandler = new JwtSecurityTokenHandler();
var key = _configuration["Jwt:Key"];

if (string.IsNullOrEmpty(key))
{
throw new InvalidOperationException("JWT Key is not configured.");
}

var keyBytes = Encoding.UTF8.GetBytes(key);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(
[
new(ClaimTypes.NameIdentifier, user.Id.ToString()),
new(ClaimTypes.Name, user.UserName),
]),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyBytes), SecurityAlgorithms.HmacSha256Signature),
Issuer = _configuration["Jwt:Issuer"],
Audience = _configuration["Jwt:Audience"]
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);

Console.WriteLine("Token: " + tokenString);
Console.WriteLine("Issuer: " + _configuration["Jwt:Issuer"]);
Console.WriteLine("Audience: " + _configuration["Jwt:Audience"]);

return Ok(new { token = tokenString });
}
В локальном хранилище я вижу, что токен сохранен. [вставьте сюда описание изображения]
Изображение

На вкладке «Сеть» я вижу, что токен находится в запросе, а ответ говорит мне, что он недействителен. [вставьте сюда описание изображения]
Изображение

Я проверил, что сгенерированный токен на jwt.io верен, и вижу, что «Издатель» и «Аудитория» верны, а также идентификатор пользователя, который я использую для входа в систему. p>
На стороне клиента я собираю токен, сгенерированный на сервере, из ответа и сохраняю его в локальном хранилище для доступа:

Код: Выделить всё

async handleSubmit() {
try {
const url = this.isRegistering
? 'http://localhost:5251/auth/register'
: 'http://localhost:5251/auth/login';

const response = await axios.post(url, {
username : this.username,
password : this.password
});

if (this.isRegistering) {
this.setMessage(response.data.message || "Registration successful! You can now log in.", false);
this.clearFields();
} else {
const token = response.data.token;

if(token) {
localStorage.setItem('token', token)
this.setMessage("Login successful!", false)
this.login({ username: this.username })
this.$router.push({ name: 'Home' });
}
else {
this.setMessage('Login failed. Token not received', true);
}

}
} catch (error) {
this.setMessage(error.response?.data?.message || "An error occurred.  Please try again.", true);
console.error('Error:', error.response.data);
}
},
Оказавшись на домашней странице, я обращаюсь к этому локальному хранилищу от клиента, чтобы получить токен и подтвердить, что пользователь, вошедший в систему, является правильным:

Код: Выделить всё

methods: {
async fetchTasks() {
try {
console.log("token", localStorage.getItem("token"));
const response = await axios.get('http://localhost:5251/api/task/upcoming', {
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
});
this.tasks = response.data;
} catch (error) {
console.error('Error fetching tasks:', error);
}
},
},

А это внутренний метод:

Код: Выделить всё

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class TaskController(TaskManagerContext context) : ControllerBase
{
private readonly TaskManagerContext _context = context;

// Method to get the next 3 tasks for a user
[HttpGet("upcoming")]
public async Task GetUpcomingTasks()
{
var userIdClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
if (userIdClaim == null)
{
return Unauthorized();
}
var userId = int.Parse(userIdClaim.Value);

// Query tasks for the authenticated user
var upcomingTasks = await _context.Tasks
.Where(t => t.UserId == userId)
.OrderBy(t => t.Date)
.Take(3)
.ToListAsync();

return Ok(upcomingTasks);
}

}

У меня та же проблема с Postman.
В моем Program.cs службы зарегистрированы в том порядке, в котором они должны быть:< /p>

Код: Выделить всё

using Microsoft.EntityFrameworkCore;
using backend.Data;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using backend.Services;

var builder = WebApplication.CreateBuilder(args);

// Database connection
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext(options =>
options.UseNpgsql(connectionString));

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Add controllers support
builder.Services.AddControllersWithViews();
builder.Services.AddCors(options => {
options.AddPolicy("AllowAllOrigins",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});

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 = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

// Apply CORS policy
app.UseCors("AllowAllOrigins");

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

app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);

app.Run();

Поэтому я не знаю, как действовать. Я все пересмотрел несколько раз и не вижу ничего плохого. Должен ли я отказаться от идеи использования JWT, потому что в моем приложении он того не стоит? Любая помощь приветствуется.

Подробнее здесь: https://stackoverflow.com/questions/791 ... pplication
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение