Аутентификация, авторизация, управление пользователями и ролями и общая безопасность в .NET - PullRequest
31 голосов
/ 03 августа 2009

Мне нужно знать, как реализовать общую безопасность для приложения на C #. Какие варианты у меня есть в этом отношении? Я бы предпочел использовать существующий каркас, если он отвечает моим потребностям - я не хочу заново изобретать колесо.

Мои требования следующие:

  • обычное имя пользователя / пароль аутентификации
  • управление пользователями - назначать права доступа пользователям
  • управление ролями - назначение пользователей ролям, назначение разрешений ролям
  • авторизация пользователей на основе их имени пользователя и роли

Я ищу бесплатную инфраструктуру / библиотеку с открытым исходным кодом, которая была проверена временем и используется сообществом .Net.

Мое приложение использует клиент-серверный подход, при этом сервер работает как служба Windows, подключаясь к базе данных SQL Server. Связь между клиентом и сервером будет осуществляться через WCF.

Еще одна важная вещь заключается в том, что мне нужно иметь возможность назначать определенные права пользователей или ролей для просмотра / обновления / удаления конкретного объекта, будь то Клиент, Продукт или т. Д. Джек может просматривать определенных 3 из 10 клиентов, но только обновлять информацию о клиентах Microsoft, Yahoo и Google и может удалять только Yahoo.

Ответы [ 7 ]

33 голосов
/ 09 августа 2009

Для грубой безопасности вам может пригодиться встроенный основной код; пользовательский объект (и их роли) управляются в .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;
}

Вы также можете написать свои собственные объекты принципала / идентичности, которые выполняют ленивые тесты / кэширование ролей, вместо того, чтобы знать их все заранее:

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
    }
}
3 голосов
/ 11 августа 2009

мой ответ, вероятно, зависит от ответа на этот вопрос: Это корпоративное приложение, которое живет в сети с Active Directory?

ЕСЛИ ответ «да», то вот шаги, которые я бы предоставил:

1) Создайте глобальные группы для вашего приложения, в моем случае у меня была группа APPUSER и группа APPADMIN.

2) Обеспечьте доступ к вашему SQL-серверу в режиме MIXED AUTHENTICATION, а затем назначьте ваши группы APPUSER в качестве входа SQL SERVER для вашей базы данных с соответствующими правами CRUD для ваших баз данных и убедитесь, что что вы обращаетесь к СЕРВЕРУ SQL с помощью Доверенное соединение = True в строке подключения.

На этом этапе ваше хранилище AD будет отвечать за аутентификацию. Поскольку вы получаете доступ к приложению через ДОВЕРЕННОЕ СОЕДИНЕНИЕ, оно передает идентификатор любой учетной записи, на которой запущено приложение, на SQL Server.

Теперь, для АВТОРИЗАЦИИ (то есть, сообщая вашему приложению, что разрешено делать зарегистрированному пользователю), достаточно просто запросить AD для получения списка групп, членом которых является зарегистрированный пользователь. Затем проверьте соответствующие имена групп и создайте свой пользовательский интерфейс на основе членства таким образом.

Таким образом работают мои приложения:

  1. При запуске приложения учетные данные основаны на вошедшем в систему пользователе, это основной аспект аутентификации (т. Е. Они могут войти в систему, поэтому они существуют)
  2. Я получаю все группы для идентификатора Windows, о котором идет речь
  3. Я проверяю стандартную группу пользователей - если эта группа не существует для рассматриваемого удостоверения Windows, то это АВАРИЙНЫЙ Сбой аутентификации
  4. Я проверяю группу пользователей ADMIN - поскольку она существует в группах пользователей, я изменяю пользовательский интерфейс, чтобы разрешить доступ к компонентам администрирования
  5. Отображение пользовательского интерфейса

Затем у меня есть либо объект PRINCIPLE с определенными правами / и т. Д., Либо я использую глобальные переменные, к которым у меня есть доступ, для определения соответствующего пользовательского интерфейса при создании моих форм (т. Е. Если мой пользователь не является членом группы ADMIN) тогда я бы спрятал все кнопки УДАЛИТЬ).

Почему я это предлагаю?

Это вопрос развертывания.

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

Кроме того, при создании новых пользователей для сети сетевой инженер (или тот, кто отвечает за создание новых сетевых пользователей) более склонен к тому, чтобы не забывать выполнять групповые назначения, пока они находятся в AD, чем тот факт, что они должны зайдите в десяток приложений, чтобы разобрать присвоения авторизации.

Это помогает в лабиринте разрешений и прав, которые должны быть предоставлены новым сотрудникам, или тем, кто покидает компанию, должно быть отказано, и он поддерживает аутентификацию и авторизацию в центральном репозитории, где он находится (то есть в AD @ Domain Controller). уровень).

3 голосов
/ 03 августа 2009

Просмотрите поставщиков членства ASP.NET . Я не думаю, что SQLMembershipProvider из коробки будет работать в вашем случае, но достаточно легко свернуть вашего собственного провайдера.

2 голосов
/ 03 августа 2009

Я бы посмотрел на что-то вроде CSLA.net: Эксперт C # 2008 Business Objects

Он должен предоставить все, что вам нужно.

1 голос
/ 03 августа 2009

WCF имеет богатую функциональность, связанную с безопасностью, обеспечивает авторизацию и аутентификацию Подробно здесь: http://msdn.microsoft.com/en-us/library/ms735093.aspx

0 голосов
/ 08 октября 2015

Я бы использовал термин «RBAC» (система контроля доступа на основе ролей) в качестве решения всех ваших требований.

Я бы не стал вдаваться в подробности для объяснения 'RBAC' здесь, скорее, я бы кратко описал его как:

В основном содержит 3 функции.

1) Аутентификация - подтверждает личность пользователя. Обычно это делается с помощью учетных записей пользователей и паролей или учетных данных.

2) Авторизация - определяет, что пользователь может делать и чего не может делать в приложении. Ex. «Изменение заказа» разрешено, но «создание нового заказа» запрещено.

3) Аудит действий пользователя над приложениями. - Он отслеживает действия пользователя над приложениями, а также кто и кому предоставил доступ?

вы можете проверить RBAC на вики здесь.

https://en.wikipedia.org/wiki/Role-based_access_control

Теперь, что касается ответа на ваши требования - одно из возможных решений - расширить членство в ASP.NET в соответствии с вашими потребностями.

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

Вы также можете проверить эту статью, чтобы лучше понять систему прав и ролей.

http://www.visual -guard.com / EN / нетто-PowerBuilder-приложения безопасности аутентификация разрешения-контроль доступ-RBAC-изделие / Dotnet-безопасность-статья-Ressources / ролевой-Access- контрольно-source_soforum.html

0 голосов
/ 11 августа 2009

Я думаю, что вы смотрите здесь на несколько отдельных проблем - не случайно большинство систем безопасности разделяют аутентификацию и авторизацию.

Для аутентификации, большой вопрос логистический. Или есть ли логичное место для жизни этих пользователей, будь то локально для приложения, в Active Directory, в каком-либо другом хранилище LDAP или даже в каком-то другом приложении. Точно, где это довольно несущественно - нам просто нужно иметь возможность надежно идентифицировать пользователей и, желательно, сделать эту задачу чужой проблемой. В конце дня вам действительно нужен уникальный идентификатор и удобство, которое Боб из бухгалтерии на самом деле Боб из бухгалтерии.

Авторизация - более интересная часть проблемы здесь. Я думаю, что если он действительно детализирован, вы действительно хотите полностью управлять этим в своем приложении, независимо от того, откуда приходят пользователи. Марк Грэвелл действительно нашел хороший способ смоделировать хотя бы кое-что из этого - использовать некоторую пользовательскую реализацию IPrincipal и PrincipalPermission для управления вещами - очень чистый способ начать работу. Кроме того, вы можете использовать такие методы, как , этот , чтобы принимать более сложные решения об авторизации довольно чистым способом.

...