Authentification, autorisation, gestion des utilisateurs et des rôles et sécurité générale dans .NET

StackOverflow https://stackoverflow.com/questions/1222974

Question

J'ai besoin de savoir comment implémenter la sécurité générale pour une application C #. Quelles sont mes options à cet égard? Je préférerais utiliser un cadre existant s'il répond à mes besoins - je ne veux pas réinventer la roue.

Mes exigences sont les suivantes:

  • authentification usuel nom d'utilisateur / mot de passe
  • gestion des utilisateurs - attribuer des autorisations aux utilisateurs
  • gestion des rôles - attribuer des rôles à des utilisateurs, attribuer des autorisations à des rôles
  • autorisation des utilisateurs en fonction de leur nom d'utilisateur et de leur rôle

Je recherche un framework / une bibliothèque libre / open-source qui a été testé et utilisé par la communauté .Net.

Mon application adopte une approche client / serveur, le serveur s'exécutant en tant que service Windows et se connectant à une base de données SQL Server. La communication entre le client et le serveur se fera via WCF.

Une autre chose importante est que je dois pouvoir attribuer des autorisations d’utilisateurs ou de rôles spécifiques à Afficher / Mettre à jour / Supprimer une entité spécifique, qu’il s’agisse d’un client, d’un produit, etc. Jack peut afficher 3 des 10 clients mais ne met à jour que les détails des clients Microsoft, Yahoo et Google, et ne peut supprimer que Yahoo.

Était-ce utile?

La solution

Pour une sécurité à grains grossiers, le code principal intégré peut être utile; l'objet utilisateur (et leurs rôles) sont contrôlés dans .NET par le "principal", mais utilement, le moteur d'exécution lui-même peut l'appliquer.

L'implémentation d'un principal peut être définie par l'implémentation et vous pouvez généralement injecter la vôtre; par exemple dans WCF .

Pour voir le temps d'exécution imposant un accès grossier (par exemple, à quelle fonctionnalité peut être accédée, mais sans limitation à quelles données spécifiques):

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...");
    }
}

Toutefois, cela n'aide pas pour un accès plus fin (par exemple, "Fred peut accéder au client A mais pas au client B").

Supplémentaire; Bien entendu, pour affiner le calcul, vous pouvez simplement vérifier les rôles requis au moment de l’exécution en cochant IsInRole sur le principal:

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;
}

Vous pouvez également écrire vos propres objets principal / identité qui effectuent des tests / mise en cache paresseux des rôles, plutôt que de devoir les connaître tous en amont:

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
    }
}

Autres conseils

Recherchez les fournisseurs d'adhésion à ASP.NET . Je ne pense pas que SQLMembershipProvider prêt à l'emploi fonctionne dans votre cas, mais il est assez facile de lancer votre propre fournisseur.

Ma réponse dépend probablement de la réponse à cette question: S'agit-il d'une application d'entreprise qui réside dans un réseau avec Active Directory?

SI la réponse est oui, voici les étapes que je voudrais fournir:

1) Créez des groupes globaux pour votre application. Dans mon cas, j’avais un groupe APPUSER et un groupe APPADMIN.

2) Accédez à votre serveur SQL Server en mode AUTHENTIFICATION MIXTE, puis affectez votre (vos) groupe (s) APPUSER en tant que LOGIN SQL SERVER à votre base de données avec les droits CRUD appropriés sur votre ou vos bases de données et assurez-vous que que vous accédez au serveur SQL avec Trusted Connection = True dans votre chaîne de connexion.

À ce stade, votre magasin AD sera responsable de l'authentification. Dans la mesure où vous accédez à l’application via une CONNEXION DE CONFIANCE, l’identité du compte qui exécute l’application sera transmise à SQL Server.

Maintenant, pour AUTORISATION (c'est-à-dire dire à votre application ce que l'utilisateur connecté est autorisé à faire), il suffit de demander à AD une liste des groupes dont l'utilisateur connecté est membre. Recherchez ensuite les noms de groupe appropriés et construisez votre interface utilisateur en vous basant sur l'appartenance de cette manière.

Le fonctionnement de mes applications est le suivant:

  1. Lors du lancement de l'application, les informations d'identification sont basées sur l'utilisateur connecté. Il s'agit du principal aspect de l'authentification (c'est-à-dire qu'ils peuvent se connecter car ils existent)
  2. Je récupère tous les groupes pour l'identité Windows en question
  3. Je recherche le groupe d'utilisateurs standard. Si ce groupe n'existe pas pour l'identité Windows en question, il s'agit d'un échec d'authentification
  4. Je vérifie le groupe d'utilisateurs ADMIN - cet élément étant présent dans les groupes d'utilisateurs, je modifie l'interface utilisateur pour autoriser l'accès aux composants d'administration
  5. Afficher l'interface utilisateur

J'ai alors soit un objet PRINCIPLE avec les droits déterminés / etc dessus, soit j'utilise des variables GLOBALES auxquelles je peux accéder pour déterminer l'interface utilisateur appropriée lors de la construction de mes formulaires (c'est-à-dire si mon utilisateur n'est pas membre du groupe ADMIN. , alors je cacherais tous les boutons DELETE).

Pourquoi est-ce que je suggère cela?

C'est une question de déploiement.

D'après mon expérience, la plupart des applications d'entreprise sont déployées par des ingénieurs réseau plutôt que par des programmeurs. C'est pourquoi il est logique qu'AD soit responsable de l'authentification / autorisation, car c'est à cet endroit que se rendent les gars du réseau quand vous discutez de l'authentification. Autorisation.

En outre, lors de la création de nouveaux utilisateurs pour le réseau, un ingénieur réseau (ou toute personne responsable de la création de nouveaux utilisateurs du réseau) est plus apte à penser à effectuer des affectations de groupe alors qu’il est IN AD que le fait qu’ils doivent aller dans une douzaine d'applications pour analyser les assignations d'autorisation.

Cela facilite le dédale d'autorisations et de droits que les nouveaux employés doivent être accordés ou que ceux qui quittent l'entreprise doivent être refusés et que l'authentification et l'autorisation sont conservées dans le référentiel central auquel il appartient (c'est-à-dire dans AD @ le contrôleur de domaine niveau).

Je pense que vous examinez ici quelques problèmes distincts. Ce n’est pas un hasard si la plupart des systèmes de sécurité séparent authentification et autorisation.

Pour l'authentification, la plus grande question est logistique. Ou bien, existe-t-il un lieu logique pour ces utilisateurs, que ce soit localement dans l'application, dans Active Directory, dans un autre magasin LDAP ou même dans une autre application? Là où c'est assez immatériel, nous devons juste être en mesure d'identifier solidement les utilisateurs et, de préférence, faire de cette tâche le problème de quelqu'un d'autre. En fin de journée, vous avez simplement besoin d’un identifiant unique et de la certitude que Bob, de la comptabilité, est bien Bob de la comptabilité.

L'autorisation est la partie la plus intéressante du problème ici. Je pense que, si elle est vraiment fine, vous voulez vraiment gérer cela entièrement dans votre application, peu importe d'où viennent les utilisateurs. Marc Gravell a vraiment trouvé un bon moyen de modéliser au moins une partie de cela - utiliser une implémentation personnalisée de IPrincipal et de PrincipalPermission pour gérer les choses est un moyen très propre de commencer. Au-delà, vous pouvez utiliser des techniques telles que celle-ci prendre des décisions d'autorisation plus complexes d'une manière plutôt propre.

J'utiliserais le terme - 'RBAC' (système de contrôle d'accès basé sur les rôles) comme solution à tous vos besoins.

Je n’irais pas beaucoup dans les détails pour expliquer «RBAC» ici, je le décrirais brièvement comme suit:

Il contient essentiellement 3 fonctionnalités.

1) Authentification - Confirme l'identité de l'utilisateur. Cela se fait généralement via des comptes d'utilisateurs, des mots de passe ou des informations d'identification.

2) Autorisation: définit ce que l'utilisateur peut faire et ne peut pas faire dans une application. Ex. La modification de la commande est autorisée, mais la création d'une nouvelle commande n'est pas autorisée.

3) Audit des actions de l'utilisateur sur les applications. - Il garde la trace des actions des utilisateurs sur les applications, ainsi que des utilisateurs et des utilisateurs autorisés?

vous pouvez vérifier RBAC sur le wiki ici.

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

Maintenant, en ce qui concerne la réponse à vos besoins - l’une des solutions possibles est d’étendre l’adhésion à ASP.NET selon vos besoins.

Et en ce qui concerne certains cadres prêts à l’emploi, je recommanderais VisualGuard pour lequel je travaille, vous devriez vérifier ceci: il fait tout ce dont vous avez besoin très facilement, et le plus important est qu'il gère tous vos utilisateurs, rôles, autorisations et applications via la console d'administration centrale et pour la définition des autorisations. , les administrateurs n’ont pas besoin des connaissances du développeur, c’est-à-dire qu’il peut créer des restrictions sur les activités via l’UI.

vous pouvez également consulter cet article pour en savoir plus sur le système basé sur les permissions et les rôles.

http://www.visual-guard.com/EN/net-powerbuilder-application-security-authentication-permission-access-control-rcac -articles / dotnet-security-article-ressources / role-based-access-control-source_soforum.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top