web-dev-qa-db-fra.com

Quelle est la meilleure façon de gérer les autorisations pour une application Web - masque de bits ou table de base de données?

J'envisage la meilleure façon de concevoir un système d'autorisations pour une application web "admin". L'application est susceptible d'avoir de nombreux utilisateurs, chacun pouvant se voir attribuer un certain rôle; certains de ces utilisateurs pourraient être autorisés à effectuer des tâches spécifiques en dehors du rôle.

Je peux penser à deux façons de concevoir ceci: une, avec une table "permissions" avec une ligne pour chaque utilisateur, et des colonnes booléennes, une pour chaque tâche, qui leur attribuent des autorisations pour effectuer ces tâches. Comme ça:

 ID utilisateur Gérer les utilisateurs Gérer les produits Gérer les promotions Gérer les commandes 
 1 vrai vrai vrai vrai 
 2 faux vrai vrai vrai 
 3 faux faux faux vrai 

Une autre façon de penser était d'utiliser un masque de bits pour stocker ces autorisations utilisateur. Cela limiterait le nombre de tâches pouvant être gérées à 31 pour un entier signé 32 bits, mais dans la pratique, il est peu probable que plus de 31 tâches spécifiques soient exécutées par un utilisateur. De cette façon, le schéma de la base de données serait plus simple et nous n'aurions pas à changer la structure de la table à chaque fois que nous ajoutions une nouvelle tâche nécessitant un contrôle d'accès. Comme ça:

 Autorisations d'ID utilisateur (masque 8 bits), seraient des entiers dans le tableau 
 1 00001111 
 2 00000111 
 3 00000001 

Quels mécanismes les gens ici ont-ils généralement utilisés et pourquoi?

Merci!

49
Hari

Je pense que c'est une règle générale de rester à l'écart des chaînes de bits mystiques qui codent le sens de l'univers.

Bien que peut-être plus maladroit, avoir une table d'autorisations possibles, une table d'utilisateurs et une table de liens entre eux est la meilleure et la plus claire façon d'organiser cela. Cela facilite également vos requêtes et votre maintenance (en particulier pour le nouveau mec).

72
Lucas Oman

que diriez-vous de créer une table d'autorisation, puis une table UserPermission pour stocker les relations?

Vous n'aurez plus jamais à modifier la structure et vous avez la possibilité d'ajouter autant d'autorisations que vous le souhaitez.

31
Levi Rosol

Je l'ai fait dans les deux sens. Mais je n'utilise plus beaucoup de masques. Une table distincte serait très bien que vous pouvez utiliser comme référence croisée, étant donné un ID utilisateur ou un ID de groupe comme clé étrangère.

UserID | Permission
===================
1      | 1              1 representing manage users
1      | 2              2 being manger products
2      | 3 

Cette façon serait plus facile à entretenir et à ajouter plus tard.

J'utiliserais également une table distincte pour gérer les autorisations.

PermissionID | Description
==========================
1            | Manage Users
2            | Manager Products
22
stephenbayer

Habituellement, j'ai une table Users, une table Roles et une table UserRoles. De cette façon, vous pouvez avoir un nombre illimité de rôles sans changer votre structure de base de données et les utilisateurs peuvent être dans plusieurs rôles.

Je force l'application à n'autoriser que les rôles (jamais les utilisateurs). Notez que la colonne "id" de la table des rôles n'est pas une colonne d'identité. Cela est dû au fait que vous devrez peut-être contrôler les ID qui sont mis dans ce tableau car votre application devra rechercher des ID spécifiques.

La structure ressemble à ceci:

create table Users (
 id int identity not null,
 loginId varchar(30) not null,
 firstName varchar(50) not null,
 etc...
)

create table Roles (
 id int not null,
 name varchar(50) not null
)

create table UserRoles (
 userId int not null,
 roleId int not null
)
8
Chad Braun-Duin

Je suggère de résumer les autorisations de votre application Web avec le concept d'un fournisseur de rôles. À partir de la version 2.0, cela vous est fourni dans .NET sous la forme System.Web.Security.RoleProvider .

L'idée de base est que vous tirez parti d'un cadre existant en écrivant vos vérifications d'autorisations par rapport au cadre plutôt qu'un mécanisme de stockage spécifique. Vous pouvez ensuite brancher n'importe quel mécanisme de stockage disponible, qu'il s'agisse d'un fichier XML, d'une base de données ou même d'un magasin d'autorisations à l'aide du Gestionnaire d'autorisations du logiciel Windows (qui vous permet de lier de manière transparente vos autorisations personnalisées à LDAP, par exemple - aucun code requis pour configurer).

Si vous décidez d'utiliser une base de données comme mécanisme de stockage, plusieurs bases de données sont prises en charge pour la création automatique des tables sous-jacentes dont l'infrastructure a besoin. Cela inclut l'exécution de .NET sur Mono et l'utilisation du modèle de fournisseur de rôles au-dessus de MySQL.

Voir Implémentation d'un fournisseur de rôles pour plus d'informations. Il est tout à fait possible que d'autres langages/environnements aient également des bibliothèques que vous pourriez utiliser pour implémenter ce concept - cela vaut la peine d'être étudié.

[~ # ~] edit [~ # ~] : Je devrais également souligner la configuration de la façon dont votre application Web est liée au mécanisme de stockage. via un fichier web.config, et ne nécessite pas de modifications de code. J'ai trouvé cela très utile pour tester une version de production d'une base de code sur ma machine locale, en utilisant un fichier XML pour imiter les autorisations au lieu du fournisseur de base de données normal - tout en modifiant deux lignes dans web.config.

L'autre chose que j'ai oublié de mentionner est que vous pouvez brancher vos propres fournisseurs personnalisés en étendant les classes de base, vous permettant de tirer parti du modèle d'autorisation tout en utilisant un système de stockage propriétaire (par exemple, des masques de bits, si vous le vouliez vraiment) .

3
J c

Vous pouvez utiliser Active Directory ou une autre implémentation LDAP si vous êtes dans un environnement géré. De cette façon, les groupes de sécurité, qui déterminent les autorisations, peuvent être gérés par le support de première ligne, en utilisant une technologie qu'ils connaissent probablement déjà.

Si votre application est emballée sous vide, +1 pour la suggestion de Levi Rosol de normaliser la base de données afin que vous puissiez avoir un modèle de données extensible dans votre application.

2
Ed Blackburn

J'ai vu un certain nombre de systèmes d'autorisations quelque peu limitées similaires à ce que vous proposez - ainsi que des systèmes vraiment terribles. Dans certaines situations simples, elles peuvent être acceptables, tant que l'application ne devient pas plus complexe. Cependant, dans de nombreux cas, ils deviennent plus compliqués et les systèmes doivent être réécrits pour s'adapter aux fonctionnalités requises.

Si vous pensez que vous pourriez avoir besoin un jour de l'expressivité, j'irais avec un système ACL complet (liste de contrôle d'accès) avec des utilisateurs et des groupes (ou des rôles). C'est-à-dire que chaque chose régie par des autorisations (par exemple, "gérer les utilisateurs", "gérer les produits") a une ACL, qui est une liste de tous les utilisateurs et groupes qui y ont accès. Ensuite, les utilisateurs sont soit ajoutés directement aux listes de contrôle d'accès pertinentes, soit ajoutés à un groupe qui est déjà membre d'une liste de contrôle d'accès.

Bien qu'ACL suggère une implémentation de liste, vous feriez mieux avec une table; cette réponse est un bon moyen.

1
TimB

Les autorisations sont généralement des mots clés avec 1, 0 ou null (indiquant hériter). Avec un système de bits, vous ne pouvez probablement pas créer d'index sur l'ID utilisateur et le mot clé d'autorisation; à la place, vous devrez analyser chaque enregistrement pour obtenir la valeur d'autorisation.

Je dirais optez pour la première option. Il me semble que la meilleure solution:

create table permissions (
    user_id INT NOT Null,
    permission VARCHAR(255) NOT NULL,
    value TINYINT(1) NULL
)
alter table `permissions` ADD PRIMARY KEY ( `user_id` , `permission` ) 
0
Dimitry

Je ne peux pas commenter car je suis nouveau sur SO, mais en ce qui concerne la réponse acceptée - un énorme avantage qui vient avec cette solution est la possibilité de gérer universellement les autorisations, au lieu de simplement si des instructions partout dans le code, ainsi que des capacités spéciales comme l'autorisation d'autorisations temporaires (autorisations ayant une date d'expiration)

0
Bobby Dawson