public class RequestLoginIsUserLoginHandler : AuthorizationHandler<AccessRequirement, string>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AccessRequirement requirement, string resource)
{
string? name = context.User.Identity?.Name;
if (name == resource)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Я вижу значения утверждений в базе данных, но context.User.Identity?.Name всегда имеет значение null. изображение
Я использую аутентификацию с использованием файлов cookie. Я добавляю претензию следующим образом:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, input.Login),
new Claim(ClaimTypes.Role, "user")
};
await userManager.AddClaimsAsync(user, claims);
Возможно у меня здесь проблемы:
[HttpPost("/login")]
public async Task<IActionResult> Login(string login, string password)
{
var user = await mediator.Send(new GetUserByLoginQuery(login));
if (user is null) return Unauthorized("wrong login");
var result = await signInManager.PasswordSignInAsync(user, password, false, false);
if (!result.Succeeded)
{
return Unauthorized("wrong password");
}
return Ok();
}
Я пытался использовать ClaimTypes.Name и свой собственный тип «Имя». Результат тот же.
Обновлено. Претензии добавляю при регистрации. Код:
[HttpPost("/register")]
public async Task<IActionResult> CreateUser(RegisterInput input)
{
var userWithSameLogin = await mediator.Send(new GetUserByLoginQuery(input.Login));
if (userWithSameLogin != null)
{
return Conflict();
}
var user = new User
{
UserName = input.Login,
FirstName = input.FirstName,
LastName = input.LastName,
PhoneNumber = input.PhoneNumber,
Email = input.Email
};
var result = await userManager.CreateAsync(user, input.Password);
if (!result.Succeeded)
{
return BadRequest(result.Errors);
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, input.Login),
new Claim(ClaimTypes.Role, "user")
};
await userManager.AddClaimsAsync(user, claims);
return Ok();
}
Эта проблема может возникнуть из-за того, что утверждение неправильно прикреплено к субъекту аутентификации или они неправильно загружаются во время процесса аутентификации.
вы можете попробовать приведенный ниже пример кода, чтобы правильно добавить утверждение, поскольку оно не показывает ноль:
Программа.cs:
builder.Services.AddControllersWithViews();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Add Identity services
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Configure Cookie Authentication
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
});
Аккаунтконтроллер.cs:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using CookieAuthDemo1.Models;
namespace CookieAuthDemo1.Controllers
{
public class AccountController : Controller
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
public AccountController(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.FindByNameAsync(model.Login);
if (user == null)
{
ModelState.AddModelError(string.Empty, "Invalid login.");
return View(model);
}
var result = await _signInManager.PasswordSignInAsync(user, model.Password, false, false);
if (result.Succeeded)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Role, "user")
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties { IsPersistent = true };
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError(string.Empty, "Invalid password.");
return View(model);
}
[HttpPost]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index", "Home");
}
}
}
@DaniilKozенко, когда вы входите в систему с помощью SignInManager.PasswordSignInAsync
, он не включает автоматически все претензии из базы данных в HttpContext.User
. По умолчанию он включает только несколько существенных утверждений. Вот почему context.User.Identity?.Name
было null
— утверждение Name
не было включено, если вы явно не добавили его после входа в систему. Заявления, добавленные вами во время регистрации, хранятся в базе данных, но они не прикрепляются автоматически к ClaimsPrincipal
во время входа в систему, если вы не извлекаете и не добавляете их вручную.
В моем коде после успешной аутентификации пользователя с помощью SignInManager.PasswordSignInAsync
я вручную добавляю утверждения в ClaimsIdentity
, а затем подписываю пользователя с этими утверждениями. Это гарантирует, что все необходимые утверждения будут включены в файл cookie аутентификации и будут доступны через HttpContext.User
на протяжении всего сеанса пользователя. дайте мне знать, если у вас все еще есть какие-либо вопросы или сомнения
Я добавляю утверждения, используя UserManager<User> во время регистрации (я добавил свой метод CreateUser в текст вопроса). Я обновил свой код, используя ваш способ добавления утверждений, и это сработало. Спасибо. Но я до сих пор не понимаю, почему мой код неприемлем.