Пользовательская аутентификация на основе ролей.СЕТЕВОЕ ЯДРО

#asp.net-core #.net-core #authorization #claims-based-identity #claims-authentication

#asp.net-core #.net-core #авторизация #идентификация на основе утверждений #утверждения-аутентификация

Вопрос:

У меня есть проект, в котором пользователи могут иметь несколько ролей, таких как кассир и продавец. Эти роли имеют одинаковые права, однако у кого-то также могут быть роли администратора и кассира. В этом случае он может получить доступ к большему количеству функций, чем администратор / кассир самостоятельно.

Я искал повсюду, но из документации я ничего не понял, поскольку сначала я думал, что политики — это правильный путь, но теперь я думаю, что нам нужна авторизация на основе утверждений.

После поиска и игры я не нашел ответов на следующие вопросы:

  1. Какие таблицы / сущности мне нужны?
  2. Можно ли это сделать без инструментов для создания лесов?
  3. Как работает весь этот процесс, как .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. Спасибо за подробный ответ. Именно то, что я искал. Я все еще думаю, что в документации об этом неясно, и мне было / было трудно понять. Приветствия.