2017-02-07 16 views
2

Я застрял в решении, которое я хотел бы предоставить в основном приложении asp.net mvc. Я хотел бы предложить решение стандартного User, Roles, Permissions в веб-приложении, используя новый подход на основе требований.Пользователи Роли Разрешения с использованием идентификатора ядра ASP.NET 3

Я слежу за логикой Бен Фостера здесь (http://benfoster.io/blog/asp-net-identity-role-claims). В приведенном ниже коде (демонстрационное качество) я иллюстрирую свою методологию, которую я прокомментирую, чтобы показать мое быстрое и грязное тестовое решение.

Задача, которую я имею, заключается в том, что она не работает.

// ПРИМЕЧАНИЕ. Я нашел ошибку и прокомментирую, где я поступил не так, если будущие пользователи ищут аналогичное решение.

Seed Class: Это быстрое и грязное решение для загрузки базы данных двумя новыми пользователями, двумя ролями и некоторыми претензиями на одну из ролей. Я сделал это как свое тестовое приложение, чтобы изучить подход претензий к управлению авторизацией для моего приложения. Мое полное решение предоставит каждому жильцу возможность создать свои собственные роли через пользовательский интерфейс, связать 1 или многие претензии к роли (-ам), а затем назначить роль пользователю. Я хотел предоставить возможность арендаторам управлять своими собственными пользователями и что они могут или не могут сделать. Это простая реализация подхода, основанного на требованиях, поскольку требования обладают гораздо большей властью, чем отношения 1: 1 с политиками.

public class DbInitializer 
{ 
    private ApplicationDbContext _context; 
    private RoleManager<ApplicationRole> _roleManager; 
    private UserManager<ApplicationUser> _userManager; 

    public DbInitializer(ApplicationDbContext context,RoleManager<ApplicationRole> roleManager, UserManager<ApplicationUser> userManager) 
    { 
     _roleManager = roleManager; 
     _userManager = userManager; 
     _context = context; 

    } 

    public async Task Initialize() 
    { 
     //RoleManager<IdentityRole> roleManager = new RoleManager<IdentityRole>(); 
     //UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(); 

     _context.Database.EnsureCreated(); 

     // Look for any students. 
     if (!_context.Users.Any()) 
     { 
      //create user and admin role 

      ApplicationUser adminUser = new ApplicationUser(); 

      adminUser.Email = "[email protected]"; 
      adminUser.UserName = "Admin"; 

      var result = await _userManager.CreateAsync(adminUser, "Password-1"); 

      var newAdminUser = await _userManager.FindByEmailAsync(adminUser.Email); 

      ApplicationRole adminRole = new ApplicationRole(); 

      adminRole.Name = "Admin"; 
      adminRole.Description = "This is the admin role."; 

      await _roleManager.CreateAsync(adminRole); 

      await _roleManager.AddClaimAsync(adminRole, new Claim("Can add roles", "add.role")); 
      await _roleManager.AddClaimAsync(adminRole, new Claim("Can delete roles", "delete.role")); 
      await _roleManager.AddClaimAsync(adminRole, new Claim("Can edit roles", "edit.role")); 

      await _userManager.AddToRoleAsync(newAdminUser, adminRole.Name); 

      //create user and basic role 

      ApplicationUser basicUser = new ApplicationUser(); 

      basicUser.Email = "[email protected]"; 
      basicUser.UserName = "Basic"; 

      var resultBasic = await _userManager.CreateAsync(basicUser, "Password-1"); 

      var newBasicUser = await _userManager.FindByEmailAsync(basicUser.Email); 

      ApplicationRole basicRole = new ApplicationRole(); 

      basicRole.Name = "Basic"; 
      basicRole.Description = "This is the basic role."; 

      await _roleManager.CreateAsync(basicRole); 

      //await _roleManager.AddClaimAsync(basicRole, new Claim("Can add roles", "add.role")); 
      //await _roleManager.AddClaimAsync(basicRole, new Claim("Can delete roles", "delete.role")); 
      //await _roleManager.AddClaimAsync(basicRole, new Claim("Can edit roles", "edit.role")); 

      await _userManager.AddToRoleAsync(newBasicUser, basicRole.Name); 

      await _context.SaveChangesAsync(); 
     } 

    } 
} 
} 

Startup.CS: После создания своих пользователей, ролей и претензий (и связывая их), мне нужно, чтобы зарегистрировать «Политики» в классе Startup.cs метода Confirgure Services. Это позволяет мне отображать претензии к политике или политикам.

public void ConfigureServices(IServiceCollection services) 
    { 
     // Add framework services. 
     services.AddDbContext<ApplicationDbContext>(options => 
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 

     services.AddIdentity<ApplicationUser, ApplicationRole>() 
      .AddEntityFrameworkStores<ApplicationDbContext>() 
      .AddDefaultTokenProviders(); 


     services.AddAuthorization(options => 
     { 
      options.AddPolicy("Add Role", 
       policy => policy.RequireClaim("Can add roles", "add.role")); 
      options.AddPolicy("Edit Role", 
       policy => policy.RequireClaim("Can edit roles", "edit.role")); 
      options.AddPolicy("Delete Role", 
       policy => policy.RequireClaim("Can delete roles", "delete.role")); 
     }); 

     services.AddMvc(); 

     services.AddTransient<DbInitializer>(); 

     // Add application services. 
     services.AddTransient<IEmailSender, AuthMessageSender>(); 
     services.AddTransient<ISmsSender, AuthMessageSender>(); 
    } 

Вид: В моем случае использования, я хотел бы ограничить кнопку «Добавить роли» от любого пользователя, который не имеет «Может добавить роли» претензии, связанные с ролью, которую они назначены на. Остальная часть кода представления не имеет отношения к делу. Проблема, с которой я столкнулся, заключается в том, что я передал имя претензии в AuthorizationService.AuthorizeAsync в качестве второго параметра, а также имя «Политика», к которому относится связанное с ним требование. С тех пор я исправил его ниже.

@model IEnumerable<ApplicationRoleListViewModel> 
@using HailMarry.Models 
@using Microsoft.AspNetCore.Authorization 
@inject IAuthorizationService AuthorizationService 

<br /> 
<div class="top-buffer"></div> 
<div class="panel panel-primary"> 
<div class="panel-heading panel-head">Application Roles</div> 
<div class="panel-body"> 
    <div class="btn-group"> 

     //Mistake 
     //@if (await AuthorizationService.AuthorizeAsync(User, "Can add roles")) 
     //Fix 
     @if (await AuthorizationService.AuthorizeAsync(User, "Add Role")) 
     { 
      <a id="createRoleButton" asp-action="AddRole" asp-controller="ApplicationRole" class="btn btn-primary"> 
       <i class="glyphicon glyphicon-plus"></i> Add Role 
      </a> 
     } 
.... 

Конечный результат: У меня есть пользователь «[email protected]», который назначен на роль «Администратор», который имеет требование «может добавить роли». Роль может иметь любое количество претензий. Я создал политику, которая имеет такое же требование «Могу добавить роли», которое я проверил в представлении через инъекционную программу IAuthorizationService AuthorizationService. Если у пользователя нет этой претензии, назначенной на их роль, тогда проверка политики, которая возвращает true или false, не покажет кнопку для добавления роли. Эта же логика проверки политики может быть добавлена ​​к контроллеру или любому другому ресурсу через DI благодаря новому промежуточному программному обеспечению .net core DI. Благодаря этому упражнению я узнал силу Identity 3, которая может использовать такие вещи, как проверка бизнес-логики. Довольно сладкий материал, хотя писателям действительно нужно больше примеров, чтобы помочь нам быстрее добраться до мяса. Во всяком случае, надеюсь, что это поможет будущим разработчикам искать аналогичное решение.

+0

Поскольку вы работаете с ролями, вы можете найти эту статью полезной в пользу использования объектов привилегий над проверками ролей: http://ardalis.com/favor-privileges-over-role-checks – ssmith

ответ

0

Я нашел этот вопрос, я сослалась на «имя» претензии против названия политики в представлении ...

Я комментируйте выше, чтобы проиллюстрировать ошибку и показать, что я делаю. Довольно мощный материал, благодаря Ben и ASP.Net для более эффективного решения авторизации более 4.5.

+1

Не публикуйте андерсеров и решений в обновленном вопросе. Поместите их сюда в ответ !!! – Tseng