Проблема JWT ASP.NET Core MVC с авторизацией при проверке ролиC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Проблема JWT ASP.NET Core MVC с авторизацией при проверке роли

Сообщение Anonymous »

Возникла проблема с аутентификацией, которую решили здесь. Сейчас возникла проблема с авторизацией, если я задаю параметр Роли, то получаю ошибку.

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

Program.cs:
namespace MySteamDBMetacritic
{
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext((options) =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddIdentity(options =>
{
options.User.RequireUniqueEmail = true;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireDigit = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
})
.AddEntityFrameworkStores().AddDefaultTokenProviders();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.IncludeErrorDetails = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
RoleClaimType = ClaimsIdentity.DefaultRoleClaimType,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
context.Response.StatusCode = 401;
context.Response.ContentType = "application/json";
var result = JsonSerializer.Serialize(new { message = "Authentication failed" });
return context.Response.WriteAsync(result);
}
};
options.TokenHandlers.Add(new BearerTokenHandler());
});

builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Admin"));
options.AddPolicy("UserPolicy", policy =>  policy.RequireRole("User"));
});

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.Configure(options =>
{
options.MultipartBodyLengthLimit = 1024 * 1024 * 20;
});

var app = builder.Build();

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

using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;

try
{
var userManager = services.GetRequiredService();
var rolesManager = services.GetRequiredService();
var context = services.GetRequiredService();
await RoleInitializer.InitializeAsync(context, userManager, rolesManager);
}
catch (Exception ex)
{
var logger = services.GetRequiredService();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}

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

app.UseRouting();

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

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

app.Run();
}
}
}
Учетные записи создаются в AccountController.cs, администратор создается в RoleInitializer.cs. Этот контроллер является примером возникновения ошибки UsersController.cs:

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

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using MySteamDBMetacritic.Models;
using MySteamDBMetacritic.ViewModels;

namespace MySteamDBMetacritic.Controllers
{
[Authorize(Roles = "Admin")]
public class UsersController : Controller
{
UserManager _userManager;

public UsersController(UserManager userManager)
{
_userManager = userManager;
}

public IActionResult Index() => View(_userManager.Users.ToList());

public IActionResult Create() => View();

[HttpPost]
public async Task Create(CreateUserViewModel model)
{
if (ModelState.IsValid)
{
User user = new User { Email = model.Email, UserName = model.UserName };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
}
return View(model);
}

public async Task Edit(int id)
{
User user = await _userManager.FindByIdAsync(id.ToString());

if (user == null)
{
return NotFound();
}

EditUserViewModel model = new EditUserViewModel { Id = user.Id, Email = user.Email, UserName = user.UserName };

return View(model);
}

[HttpPost]
public async Task Edit(EditUserViewModel model)
{
if (ModelState.IsValid)
{
User user = await _userManager.FindByIdAsync(model.Id.ToString());

if (user != null)
{
user.Email = model.Email;
user.UserName = model.UserName;

var result = await _userManager.UpdateAsync(user);

if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
}
}

return View(model);
}

[HttpPost]
public async Task Delete(int id)
{
User user = await _userManager.FindByIdAsync(id.ToString());

if (user != null)
{
IdentityResult result = await _userManager.DeleteAsync(user);
}

return RedirectToAction("Index");
}
}
}

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

AccountController.cs

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

public class AccountController : Controller
{
private readonly ILogger _logger;
private readonly ApplicationDbContext _context;
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly IConfiguration _configuration;

public AccountController(ILogger logger, ApplicationDbContext context, UserManager userManager, SignInManager signInManager, IConfiguration configuration)
{
_context = context;
_logger = logger;
_userManager = userManager;
_signInManager = signInManager;
_configuration = configuration;
}

[HttpGet]
public IActionResult Register()
{
return View();
}

[HttpPost]
public async Task  Register([FromBody]RegisterViewModel model)
{
if (ModelState.IsValid)
{
User user = new User { Email = model.Email, UserName = model.UserName };

if (_userManager.Users
.FirstOrDefault(x => x.Email == user.Email) != default(User))
{
return View(model);
}

var result = await _userManager.CreateAsync(user, model.Password);

if (result.Succeeded)
{
_context.SaveChanges();
await _signInManager.SignInAsync(user, false);
return Json(new { token = Token(model.UserName, model.Password), returnUrl = Url.Action("Index", "Game") });
}
else
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
}

return View(model);
}

[HttpGet]
public IActionResult Login(string returnUrl = null)
{
return View(new LoginViewModel { ReturnUrl = returnUrl });
}

[HttpPost]
public async Task Login([FromBody]LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, false);

if (result.Succeeded)
{
if (!string.IsNullOrEmpty(model.ReturnUrl) && Url.IsLocalUrl(model.ReturnUrl))
{
return Json(new { token = ((JsonResult)Token(model.UserName, model.Password)).Value, returnUrl = model.ReturnUrl});
}
else
{
return Json(new { token = ((JsonResult)Token(model.UserName, model.Password)).Value, returnUrl = Url.Action("Index", "Game") });
}
}
else
{
ModelState.AddModelError("", "Incorrect username or password");
}
}

return View(model);
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index", "Game");
}

public async Task ChangePassword(int id)
{
User user = await _userManager.FindByIdAsync(id.ToString());

if (user == null)
{
return NotFound();
}

ChangePasswordViewModel model = new ChangePasswordViewModel { Id = user.Id, Email = user.Email };

return View(model);
}

[HttpPost]
public async Task  ChangePassword(ChangePasswordViewModel model)
{
if (ModelState.IsValid)
{
User user = await _userManager.FindByIdAsync(model.Id.ToString());

if (user != null)
{
var _passwordValidator = HttpContext.RequestServices.GetService(typeof(IPasswordValidator)) as IPasswordValidator;
var _passwordHasher = HttpContext.RequestServices.GetService(typeof(IPasswordHasher)) as IPasswordHasher;

IdentityResult result = await _passwordValidator.ValidateAsync(_userManager, user, model.NewPassword);

if (result.Succeeded)
{
user.PasswordHash = _passwordHasher.HashPassword(user, model.NewPassword);
await _userManager.UpdateAsync(user);
return RedirectToAction("Index");
}
else
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
}
else
{
ModelState.AddModelError(string.Empty, "User is missing");
}
}

return View(model);
}

public IActionResult Token(string username, string password)
{
var identity = GetIdentity(username, password).GetAwaiter().GetResult();

if (identity == null)
{
return BadRequest(new { errorText = "Invalid username or password." });
}

var now = DateTime.Now;

var jwt = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
notBefore: now,
claims: identity.Claims,
expires: now.Add(TimeSpan.FromMinutes(double.Parse(_configuration["Jwt:ExpiresMinutes"]))),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])), SecurityAlgorithms.HmacSha256));
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

var response = new
{
access_token = encodedJwt,
username = identity.Name
};

return Json(response);
}

private async Task GetIdentity(string username, string password)
{
User user = await _userManager.FindByNameAsync(username);

if (user != null)
{
var claims = new List
{
new Claim(ClaimsIdentity.DefaultNameClaimType, user.UserName),
new Claim(ClaimsIdentity.DefaultRoleClaimType, string.Join(',',_userManager.GetRolesAsync(user).Result))
};

ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, "Token",
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);

return claimsIdentity;
}

return null;
}
}
Проверил, роль назначена.

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

RoleInitializer
, выполнить каждую стартовую программу, GetRoleAsync вернет «Администратор»

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

using Microsoft.AspNetCore.Identity;
using MySteamDBMetacritic.Db;
using MySteamDBMetacritic.Models;

namespace MySteamDBMetacritic.Classes
{
public class RoleInitializer
{
public static async Task InitializeAsync(ApplicationDbContext _context, UserManager userManager, RoleManager  roleManager)
{
string adminEmail = "admin@gmail.com";
string password = "aA12345!";

if (await roleManager.FindByNameAsync("Admin") == null)
{
await roleManager.CreateAsync(new IdentityRole("Admin"));
}

if (await roleManager.FindByNameAsync("User") == null)
{
await roleManager.CreateAsync(new IdentityRole("User"));
}

if (await userManager.FindByNameAsync("Admin") == null)
{
User admin = new User { Email = adminEmail, UserName = "Admin" };
IdentityResult result = await userManager.CreateAsync(admin, password);

if (result.Succeeded)
{
await userManager.AddToRoleAsync(admin, "Admin");
}
}
else
{
User? admin = await userManager.FindByNameAsync("Admin");
var result = await userManager.GetRolesAsync(admin);

if (!result.Contains("Admin"))
{
await userManager.AddToRoleAsync(admin, "Admin");
}
}

await _context.SaveChangesAsync();
}
}
}
Изображение

Я сделал провел небольшое исследование и не нашел ничего, что могло бы мне помочь, я просто добавил

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

TokenValidationParameters RoleClaimType = ClaimsIdentity.DefaultRoleClaimType
и мне это не помогло.
Когда я создаю токен JWT, все хорошо:
Изображение
Но когда я проверяю HttpContext, появляется нет утверждения "роли":
Изображение


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

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Проблема JWT ASP.NET Core MVC с авторизацией при проверке роли
    Anonymous » » в форуме C#
    0 Ответы
    22 Просмотры
    Последнее сообщение Anonymous
  • Проблема JWT ASP.NET Core MVC с авторизацией при проверке роли
    Anonymous » » в форуме C#
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • Роли удостоверений ASP.NET Core EF при использовании схемы носителя JWT
    Anonymous » » в форуме C#
    0 Ответы
    20 Просмотры
    Последнее сообщение Anonymous
  • Веб-API ASP.NET — аутентификация Google с авторизацией JWT
    Anonymous » » в форуме C#
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous
  • Веб-API ASP.NET — аутентификация Google с авторизацией JWT
    Anonymous » » в форуме C#
    0 Ответы
    12 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»