#asp.net-core #.net-core #authorization #claims-based-identity #claims-authentication
#asp.net-core #.net-core #авторизация #идентификация на основе утверждений #утверждения-аутентификация
Вопрос:
У меня есть проект, в котором пользователи могут иметь несколько ролей, таких как кассир и продавец. Эти роли имеют одинаковые права, однако у кого-то также могут быть роли администратора и кассира. В этом случае он может получить доступ к большему количеству функций, чем администратор / кассир самостоятельно.
Я искал повсюду, но из документации я ничего не понял, поскольку сначала я думал, что политики — это правильный путь, но теперь я думаю, что нам нужна авторизация на основе утверждений.
После поиска и игры я не нашел ответов на следующие вопросы:
- Какие таблицы / сущности мне нужны?
- Можно ли это сделать без инструментов для создания лесов?
- Как работает весь этот процесс, как .NET CORE узнает, на какие роли смотреть? Как я могу использовать пользовательские роли?
Если бы кто-нибудь мог мне помочь с этим, я был бы признателен.
Приветствия.
Ответ №1:
Один из способов — использовать идентификатор и авторизовать пользователя с помощью [Authorize(Roles ="Admin")]
.
Если вы хотите обойтись без инструментов создания каркасов, вы можете использовать аутентификацию токена jwt или аутентификацию с использованием файлов cookie.
Вот простая демонстрация того, как использовать проверку подлинности с использованием файлов cookie:
Модель:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public List<UserRole> UserRoles { get; set; }
}
public class Role
{
public int Id { get; set; }
public string RoleName { get; set; }
public List<UserRole> UserRoles { get; set; }
}
public class UserRole
{
public int UserId { get; set; }
public User User { get; set; }
public int RoleId { get; set; }
public Role Role { get; set; }
}
public class LoginModel
{
public string Name { get; set; }
public string Password { get; set; }
}
Контроллер:
public class HomeController : Controller
{
private readonly YouDbContext _context;
public HomeController(YouDbContext context)
{
_context = context;
}
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginModel model)
{
var claims = new List<Claim>{};
var user = _context.User
.Include(u=>u.UserRoles)
.ThenInclude(ur=>ur.Role)
.Where(m => m.Name == model.Name).FirstOrDefault();
if(user.Password==model.Password)
{
foreach(var role in user.UserRoles.Select(a=>a.Role.RoleName))
{
var claim = new Claim(ClaimTypes.Role, role);
claims.Add(claim);
}
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties{};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
}
return View("Index");
}
public IActionResult Index()
{
return View();
}
//allow Cashier
[Authorize(Roles = "Cashier")]
public IActionResult Privacy()
{
return View();
}
//allow Admin
[Authorize(Roles = "Admin")]
public IActionResult AllowAdmin()
{
return View();
}
//allow both of the Admin and Cashier
[Authorize(Roles = "Admin,Cashier")]
public IActionResult AllowBoth()
{
return View();
}
//user has no rights to access the page
public IActionResult AccessDenied()
{
return View();
}
//log out
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(
CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Index");
}
}
DbContext:
public class YouDbContext: DbContext
{
public YouDbContext(DbContextOptions<YouDbContext> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
public DbSet<Role> Role { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserRole>()
.HasKey(bc => new { bc.UserId, bc.RoleId });
modelBuilder.Entity<UserRole>()
.HasOne(bc => bc.User)
.WithMany(b => b.UserRoles)
.HasForeignKey(bc => bc.UserId);
modelBuilder.Entity<UserRole>()
.HasOne(bc => bc.Role)
.WithMany(c => c.UserRoles)
.HasForeignKey(bc => bc.RoleId);
}
}
Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Home/Login";
options.AccessDeniedPath = "/Home/AccessDenied";
});
services.AddDbContext<WebApplication1Context>(options =>
options.UseSqlServer(Configuration.GetConnectionString("WebApplication1Context")));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Результат:
Комментарии:
1. Спасибо за подробный ответ. Именно то, что я искал. Я все еще думаю, что в документации об этом неясно, и мне было / было трудно понять. Приветствия.