Аутентификация, авторизация, управление пользователями и ролями и общая безопасность in.NET
Мне нужно знать, как реализовать общую безопасность для приложения c#. Какие у меня есть варианты в этом плане? Я бы предпочел использовать существующую структуру, если она отвечает моим потребностям - я не хочу заново изобретать колесо.
мои требования следующие:
- обычное имя пользователя / пароль аутентификации
- управление пользователями-назначение разрешений пользователям
- управление ролями-назначение пользователей ролям, назначение разрешений к ролям
- авторизация пользователей на основе имени пользователя и роли
Я ищу бесплатную / с открытым исходным кодом фреймворк / библиотеку, которая была проверена временем и используется сообществом .Net.
мое приложение использует подход клиент / сервер, при этом сервер работает как служба windows, подключаясь к базе данных SQL Server. Связь между клиентом и сервером будет осуществляться через WCF.
еще одна вещь, которая важна, это то, что мне нужно возможность назначать определенным пользователям или ролям разрешения на просмотр / обновление / удаление определенной сущности, будь то клиент или продукт и т. д. Например, Джек может просматривать определенные 3 из 10 клиентов, но только обновлять данные клиентов Microsoft, Yahoo и Google и может только удалять Yahoo.
7 ответов
для крупнозернистой безопасности может оказаться полезным встроенный основной код; объект пользователя (и их роли) управляются в .NET "Принципалом", но с пользой сама среда выполнения может обеспечить это.
реализация принципала может быть определена реализацией, и вы обычно можете ввести свой собственный;например в WCF.
чтобы увидеть время выполнения, обеспечивающее грубый доступ (т. е. какой функциональность можно, но не ограничивается какой специфической сведения):
static class Roles {
public const string Administrator = "ADMIN";
}
static class Program {
static void Main() {
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Fred"), new string[] { Roles.Administrator });
DeleteDatabase(); // fine
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Barney"), new string[] { });
DeleteDatabase(); // boom
}
[PrincipalPermission(SecurityAction.Demand, Role = Roles.Administrator)]
public static void DeleteDatabase()
{
Console.WriteLine(
Thread.CurrentPrincipal.Identity.Name + " has deleted the database...");
}
}
однако это не помогает с мелкозернистым доступом (т. е. "Фред может получить доступ к клиенту A, но не клиенту B").
дополнительные; конечно, для мелкозернистых, вы можете просто проверить необходимые роли во время выполнения проверки IsInRole
основные:
static void EnforceRole(string role)
{
if (string.IsNullOrEmpty(role)) { return; } // assume anon OK
IPrincipal principal = Thread.CurrentPrincipal;
if (principal == null || !principal.IsInRole(role))
{
throw new SecurityException("Access denied to role: " + role);
}
}
public static User GetUser(string id)
{
User user = Repository.GetUser(id);
EnforceRole(user.AccessRole);
return user;
}
вы также можете написать свои собственные объекты principal / identity, которые выполняют ленивые тесты / кэширование ролей, а не знать их всех наперед:
class CustomPrincipal : IPrincipal, IIdentity
{
private string cn;
public CustomPrincipal(string cn)
{
if (string.IsNullOrEmpty(cn)) throw new ArgumentNullException("cn");
this.cn = cn;
}
// perhaps not ideal, but serves as an example
readonly Dictionary<string, bool> roleCache =
new Dictionary<string, bool>();
public override string ToString() { return cn; }
bool IIdentity.IsAuthenticated { get { return true; } }
string IIdentity.AuthenticationType { get { return "iris scan"; } }
string IIdentity.Name { get { return cn; } }
IIdentity IPrincipal.Identity { get { return this; } }
bool IPrincipal.IsInRole(string role)
{
if (string.IsNullOrEmpty(role)) return true; // assume anon OK
lock (roleCache)
{
bool value;
if (!roleCache.TryGetValue(role, out value)) {
value = RoleHasAccess(cn, role);
roleCache.Add(role, value);
}
return value;
}
}
private static bool RoleHasAccess(string cn, string role)
{
//TODO: talk to your own security store
}
}
посмотрите в ASP.NET ' S поставщики членства. Я не думаю, что из коробки SQLMembershipProvider будет работать в вашем случае, но достаточно легко свернуть собственного поставщика.
мой ответ, вероятно, зависит от ответа на этот вопрос: это корпоративное приложение, которое живет в сети с Active Directory?
Если ответ да, то это шаги, которые я бы предоставил:
1) Создайте глобальные группы для вашего приложения, в моем случае у меня была группа APPUSER и группа APPADMIN.
2) иметь доступ к SQL Server в режиме смешанной аутентификации, а затем назначьте группу (группы) пользователей APPUSER в качестве имени входа SQL SERVER в базу данных с соответствующими правами CRUD на вашу БД и убедитесь, что вы получаете доступ к SQL SERVER с помощью Доверенное Соединение = True в строке подключения.
на данный момент ваш магазин объявлений будет отвечать за аутентификацию. Поскольку вы обращаетесь к приложению через доверенное соединение, оно передаст идентификатор любой учетной записи, запускающей приложение, на SQL Server.
теперь для авторизации (т. е. рассказывая вашему приложению, что входящий в систему пользователь может делать) это простой вопрос запроса объявления для списка групп, в которых вошел пользователь является членом. Затем проверьте соответствующие имена групп и создайте свой пользовательский интерфейс на основе членства таким образом.
то, как работают мои приложения, таково:
- запуск приложения, учетные данные основаны на зарегистрированном пользователе, это основной аспект аутентификация (т. е. они могут войти в систему, поэтому они существуют)
- я получаю все группы для идентификатора Windows в вопросе
- я проверяю стандартную группу пользователей - если эта группа не существует для удостоверения Windows, о котором идет речь, то это ошибка аутентификации
- я проверяю группу пользователей ADMIN -- с этим, существующим в группах пользователя, я изменяю пользовательский интерфейс, чтобы разрешить доступ к компонентам администрирования
- отобразить UI
затем у меня есть либо объект принципа с определенными правами/etc на нем, либо я использую глобальные переменные, к которым я могу получить доступ, чтобы определить соответствующий пользовательский интерфейс при создании моих форм (т. е. если мой пользователь не является членом группы администратора, то я бы скрыл все кнопки удаления).
Почему я предлагаю это?
Это вопрос развертывания.
по моему опыту, большинство корпоративных приложений развертываются по Сети Инженеры, а не программисты-поэтому, имея аутентификацию/авторизацию, чтобы быть ответственностью AD имеет смысл, так как именно туда отправляются сетевые ребята, когда вы обсуждаете аутентификацию/авторизацию.
кроме того, во время создания новых пользователей для сети сетевой инженер (или тот, кто отвечает за создание новых пользователей сети) более склонен помнить о выполнении групповых назначений, пока они находятся в AD, чем тот факт, что они должны идти в дюжину приложения для разбора назначений авторизации.
Это помогает с лабиринтом разрешений и прав, которые должны быть предоставлены новым сотрудникам или тем, кто покидает компанию, нужно отказать, и он поддерживает аутентификацию и авторизацию в Центральном репозитории, где он принадлежит (т. е. на уровне контроллера домена AD@).
Я бы посмотрел на что-то вроде CSLA.net: Эксперт C# 2008 Бизнес-Объекты
Он должен обеспечить все, что вам требуется.
WCF имеют богатую функциональность, связанную с безопасностью, обеспечивает как авторизацию, так и аутентификацию. Подробнее здесь: http://msdn.microsoft.com/en-us/library/ms735093.aspx
Я думаю, что вы смотрите на несколько отдельных проблем здесь-это не случайно большинство систем безопасности отдельной аутентификации и авторизации.
для аутентификации больший вопрос является логистическим. Или есть логическое место для этих пользователей, будь то локально для приложения, в Active Directory, в каком-либо другом хранилище LDAP или даже в каком-либо другом приложении. Именно там, где это довольно нематериально-нам просто нужно иметь возможность надежно идентифицировать пользователей и желательно сделать это задача чужой проблемы. В конце концов, вам просто нужен уникальный идентификатор и комфорт, что Боб из бухгалтерского учета на самом деле Боб из бухгалтерского учета.
авторизация является более интересной частью проблемы здесь. Я думаю, если это действительно мелкозернистый, вы действительно хотите управлять этим полностью в своем приложении, независимо от того, откуда приходят пользователи. Марк Гравелл действительно нашел хороший способ смоделировать хотя бы часть этого-использовать некоторую пользовательскую реализацию IPrincipal и PrincipalPermission для управления вещами-очень чистый способ начать работу. Кроме того, вы можете использовать такие методы, как этот принимать более сложные решения об авторизации довольно чистым способом.
Я бы использовал термин - 'RBAC' (система управления доступом на основе ролей) в качестве решения для всех ваших требований.
Я бы не стал вдаваться в подробности для объяснения "RBAC" здесь, скорее я бы кратко изложил его ниже.
Он в основном содержит 3 функции.
1) аутентификации подтверждает личность пользователя. Обычно это делается через учетные записи пользователей и пароли или учетные данные.
2) авторизация-определяет, что пользователь может и не может сделать в приложение. Бывший. ‘Изменение порядка’ а ‘создание нового заказа не допускаются.
3) аудит действий пользователя в приложениях. - Он отслеживает действия пользователя в приложениях, а также Кто предоставил какой доступ к каким пользователям?
вы можете проверить RBAC на wiki здесь.
https://en.wikipedia.org/wiki/Role-based_access_control
теперь, относительно ответа к вашим требованиям-одно из возможного решения к расширить Asp.Net членство в соответствии с потребностями.
и что касается некоторых готовых к использованию рамок, я бы рекомендовал VisualGuard для которого я работаю, вы должны проверить это, он делает все, что вам нужно, очень легко, и что самое главное, он управляет всеми вашими пользователями, ролями, разрешениями и приложениями через консоль Центрального администрирования, а для определения разрешений администраторы не требуют знаний разработчика, i.e он / она может создавать ограничения на деятельности посредством пользовательского интерфейса.
вы также можете проверить эту статью, чтобы иметь больше понимания на основе разрешений и ролей системы.