6

Будучи относительно новым ASP MVC, я неуверен, который бы лучше удовлетворить мои потребности. Я создал сайт интрасети с использованием проверки подлинности Windows, и я могу защитить контроллеры и действия с использованием ролей Active Directory, например.ASP.NET MVC Как создать пользовательский поставщик роли

Мне нужно определить свои собственные роли безопасности независимо от ролей AD. Требуемая функциональность, что аутентифицированные пользователи предоставляются доступ к конкретным действиям в соответствии с одной или нескольких ролей, связанных с их профилем в моей базе данных приложений, например: «Менеджер», «Пользователь», «Гость», «Аналитик», «Разработчик» и т.д.

Как создать пользовательский поставщик роли и/или атрибут (ы) пользовательских авторизации?

EDIT: Отредактированный название и вопрос, чтобы сделать его проще для других пользователей, чтобы определить содержание поста.

+0

Я думаю, что прошение о лучшем/чистом способе будет получать много разных ответов. Хороший подход - сверху вниз. То есть - авторизация на уровне контроллера, а затем ограничение на уровне метода/действия в зависимости от потребностей. Вы также можете реализовать базовый контроллер области, а затем каждый контроллер в этой области реализует базу. Контроллер базовой зоны может перенаправлять на соответствующую страницу, если уровень авторизации не выполняется. – Benthon

ответ

8

Мое решение было создание пользовательского поставщика ролей. Вот шаги, которые я взял, в случае, если кто-либо еще нуждается в помощи позже:

Создание пользовательских пользователей и ролей классов

using Microsoft.AspNet.Identity.EntityFramework; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
namespace Security.Models.Security 
{ 
    public class AppRole : IdentityRole 
    { 
    } 
} 

и

using Microsoft.AspNet.Identity.EntityFramework; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
namespace Security.Models.Security 
{ 
    public class AppUser : IdentityUser 
    { 
    } 
} 

Настройка базы данных контекст

using Microsoft.AspNet.Identity.EntityFramework; 
using Security.Models.Security; 
using System; 
using System.Collections.Generic; 
using System.Data.Entity; 
using System.Linq; 
using System.Web; 

namespace Security.Models.DAL 
{ 
    public class UserContext : IdentityDbContext<AppUser> 
    { 
     public UserContext() : base("UserContext") 
     { 
      Database.SetInitializer<UserContext>(new CreateDatabaseIfNotExists<UserContext>()); 
     } 
    } 
} 

Создать свой поставщика ролей и реализовать следующие методы

using Security.Models.DAL; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Security; 

namespace Security.Models.Security 
{ 
    public class AppRoleProvider : RoleProvider 
    { 
     public override string[] GetAllRoles() 
     { 
      using (var userContext = new UserContext()) 
      { 
       return userContext.Roles.Select(r => r.Name).ToArray(); 
      } 
     } 

     public override string[] GetRolesForUser(string username) 
     { 
      using (var userContext = new UserContext()) 
      { 
       var user = userContext.Users.SingleOrDefault(u => u.UserName == username); 
       var userRoles = userContext.Roles.Select(r => r.Name); 

       if (user == null) 
        return new string[] { }; 
       return user.Roles == null ? new string[] { } : 
        userRoles.ToArray(); 
      } 
     } 

     public override bool IsUserInRole(string username, string roleName) 
     { 
      using (var userContext = new UserContext()) 
      { 
       var user = userContext.Users.SingleOrDefault(u => u.UserName == username); 
       var userRoles = userContext.Roles.Select(r => r.Name); 

       if (user == null) 
        return false; 
       return user.Roles != null && 
        userRoles.Any(r => r == roleName); 
      } 
     } 
    } 
} 

Изменить ваш web.config настроить ссылку подключения к базе данных и поставщика роли

<connectionStrings> 
    <add name="UserContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\UserContext.mdf;Initial Catalog=UserContext;Integrated Security=SSPI;" providerName="System.Data.SqlClient" /> 
</connectionStrings> 

и

<system.web> 
    ... 
    <authentication mode="Windows" />   
    <roleManager enabled="true" defaultProvider="AppRoleProvider"> 
     <providers> 
     <clear/> 
     <add name="AppRoleProvider" type="Security.Models.Security.AppRoleProvider" connectionStringName = "UserContext"/> 
     </providers> 
     ... 
    </roleManager> 
    </system.web> 

менеджера пакетов консоли, включите миграции

enable-migrations 

Во вновь созданных конфигураций.CS настроить пользователей/ролей магазинов и менеджеров и настроить менеджер пользователей валидатор принять «\» символы

namespace Security.Migrations 
{ 
    using Microsoft.AspNet.Identity; 
    using Microsoft.AspNet.Identity.EntityFramework; 
    using Security.Models.Security; 
    using System; 
    using System.Data.Entity; 
    using System.Data.Entity.Migrations; 
    using System.Linq; 

    internal sealed class Configuration : DbMigrationsConfiguration<Security.Models.DAL.UserContext> 
    { 
     public Configuration() 
     { 
      AutomaticMigrationsEnabled = true; 
      ContextKey = "Security.Models.DAL.UserContext"; 
     } 

     protected override void Seed(Security.Models.DAL.UserContext db) 
     { 
      // Set up the role store and the role manager 
      var roleStore = new RoleStore<AppRole>(db); 
      var roleManager = new RoleManager<AppRole>(roleStore); 

      // Set up the user store and the user mananger 
      var userStore = new UserStore<AppUser>(db); 
      var userManager = new UserManager<AppUser>(userStore); 

      // Ensure that the user manager is able to accept special characters for userNames (e.g. '\' in the 'DOMAIN\username')    
      userManager.UserValidator = new UserValidator<AppUser>(userManager) { AllowOnlyAlphanumericUserNames = false }; 

      // Seed the database with the administrator role if it does not already exist 
      if (!db.Roles.Any(r => r.Name == "Administrator")) 
      { 
       var role = new AppRole { Name = "Administrator" }; 
       roleManager.Create(role); 
      } 

      // Seed the database with the administrator user if it does not already exist 
      if (!db.Users.Any(u => u.UserName == @"DOMAIN\admin")) 
      { 
       var user = new AppUser { UserName = @"DOMAIN\admin" }; 
       userManager.Create(user); 
       // Assign the administrator role to this user 
       userManager.AddToRole(user.Id, "Administrator"); 
      } 
     } 
    } 
} 

менеджера пакетов консоли, убедитесь, создается база данных и высевают

update-database 

Создайте специальный атрибут авторизации, который будет перенаправлен на страницу отказа при доступе при сбое.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 

namespace Security.Models.Security 
{ 
    public class AccessDeniedAuthorizationAttribute : AuthorizeAttribute 
    { 
     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 
      base.OnAuthorization(filterContext); 

      if(filterContext.Result is HttpUnauthorizedResult) 
      { 
       filterContext.Result = new RedirectResult("~/Home/AccessDenied"); 
      } 
     } 
    } 
} 

Все готово! Теперь вы можете создать страницу отказа в доступе (в данном случае ~/Home/AccessDenied) и применить атрибут к любому действию, например.

using Security.Models.Security; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 

namespace Security.Controllers 
{ 
    public class HomeController : Controller 
    { 
     ...  

     [AccessDeniedAuthorizationAttribute(Roles = "Administrator")] 
     public ActionResult SecureArea() 
     { 
      return View(); 
     } 

     public ActionResult AccessDenied() 
     { 
      return View(); 
     } 

     ... 
    } 
} 

Надеюсь, это поможет кому-то в будущем. Удачи!