Options pour extraire les éléments de contenu basés sur le rôle de la database

J'ai besoin d'apporter du contenu basé sur les rôles (plusieurs morceaux résultant dans un object) de la database à une couche de service. L'access à chaque élément de contenu dépend du rôle de l'user. Si le rôle user n'a pas access à une pièce, celle-ci sera vide. Ce n'est pas une application énorme, juste une méthode de service Web exposant du contenu basé sur des rôles.

Je pourrais le faire de trois façons.

1) En fonction du rôle de l'user, effectuez des appels de database pour chaque élément de contenu.

Avantages – Les rôles sont gérés dans le code, ce qui aide la logique métier (?) À restr dans le code. Ne ramène que datatables nécessaires.

Inconvénients – Appels db multiples. Le code doit être modifié lorsqu'un nouveau rôle est ajouté. (sauf si une logique métier vraiment compliquée est utilisée.)

2) Effectuez un seul appel db et ramenez tous les éléments de contenu sous forme d'sets de résultats distincts. Parcourez les sets et obtenez des pièces en fonction du rôle de l'user.

Pros – Appel db unique. Les rôles sont gérés dans le code.

Contre – Le code doit être modifié pour les nouveaux rôles. Des données supplémentaires sont ramenées bien qu'elles ne soient pas nécessaires. Ces requêtes inutiles peuvent append quelques secondes.

3) Envoyer les rôles à la database et get chaque pièce en fonction de l'access au rôle.

Avantages – appel db unique. Ne ramène que ce qui est nécessaire. Pas besoin de changer le code pour les nouveaux rôles car seule la procédure stockée doit changer.

Contre – La logique métier dans la database?


Il me semble que # 3> # 2> # 1. (overriden> signifier mieux que)

Quelqu'un a-t-il une idée de la meilleure approche?

Mise à jour basée sur quelques commentaires, quelques détails supplémentaires sont ci-dessous.

Le rôle de l'user est obtenu à partir d'un autre système. # 3 serait idéalement le passer à la DB, et en termes bruts pour la DB, returnner datatables comme si user_role = "admin", get toutes les pièces, pour "éditeur" get des pièces de contenu 1,3 et 55. Encore une fois, c'est pas une grande application où la gestion des rôles est faite dans la DB. C'est une méthode de service Web pour exposer des données pour plusieurs entresockets.

Nous ne pouvons évidemment pas utiliser ce model pour gérer les rôles dans une application. Mais pour un contrôle d'access au niveau de la méthode comme dans ce scénario, je crois que le # 3 est le meilleur moyen. Comme les rôles proviennent d'un autre système que celui où réside le contenu, la logique de contrôle de l'access aux différentes pièces de contenu doit résider quelque part. La database semble être le bon endroit pour avoir une solution maintenable, évolutive et less encombrante dans ce scénario particulier. Peut-être, même créer une table de consultation dans le contenu db pour maintenir les rôles et l'access aux pièces de contenu pour donner une idée de la séparation «données» et «logique», plutôt que d'avoir un udf pour effectuer la logique.

Si personne ne peut penser à un cas valide contre # 3, je pense que je vais aller de l'avant avec ça.

Je choisirais toujours l'option 3 et l'appliquerais dans la database elle-même.

La security est mieux gérée au plus près des données réelles pour de nombreuses raisons. Regardez-le de cette façon: Il est plus commun d'append une application supplémentaire dans une langue différente que de lancer un model de database. Lorsque cela se produit, tout votre code de gestion de rôle doit être dupliqué.

Ou disons que l'application est complètement contournée pendant un hack. La database devrait toujours renforcer sa security.

Enfin, bien que les gens aiment séparer la «logique métier» de leurs données, la réalité est que la plupart des données n'ont aucune signification sans cette logique. En outre, la «logique de security» n'est pas la même chose que la «logique métier» ordinaire. Il est là pour vous protéger et protéger vos clients. Mais c'est mes 0,02 $.


En regardant vos autres options:

2) Vous envoyez trop de données au client. C'est à la fois une security et une performance non non. Que faire si votre application n'est pas celle qui effectue la request de données? Que faire si vous avez un léger bug dans votre application qui montre trop à l'user?

1 et 2) Les deux nécessitent un redeployment même pour de légères modifications logiques (comme la correction du bug mythique ci-dessus). Cela pourrait ne pas être désiré. Personnellement, je préfère apporter des modifications mineures aux procédures stockées plutôt que redéployer du code. Dans le cas d'un projet assez important, il peut être difficile de savoir exactement ce qui est en train d'être déployé et, en règle générale, le potentiel de problèmes est plus élevé.

METTRE À JOUR

Basé sur vos informations supplémentaires, je suggère toujours de coller avec # 3.

Cela dépend de la structure de votre database.

Si vous pouvez gérer les droits d'access dans la database, vous pouvez avoir un design de table

Content Table ContentId Content Role Table RoleID RoleName ContentAccess Table ContentID RoleID 

Passer ensuite dans le rôle en tant que paramètre de requête n'est absolument pas une «logique métier dans la database». Vous devez évidemment écrire une requête pour joindre les tables "content" et "contentaccess" afin de récupérer ces lignes dans la table de contenu où se trouve un logging correspondant dans ContentAccess pour le rôle de l'user actuel.

Si votre application utilise du code pour déterminer si un user est autorisé à voir un contenu spécifique, cela ne fonctionne pas. L'exemple le plus "if user_role = "admin" then get all content, if user_role = "editor" get items 1, 3 and 55 serait "if user_role = "admin" then get all content, if user_role = "editor" get items 1, 3 and 55 ". Je dirais que ce n'est pas vraiment un design maintenable – mais vous dites que l'application n'est pas vraiment énorme pour commencer, donc ce n'est peut-être pas une grosse affaire.

Idéalement, je voudrais refactoriser l'application pour «gérer les droits d'access comme des données, pas du code», parce que vous mentionnez la maintenabilité comme une exigence.

Si vous ne voulez pas faire cela, l'option 1 est la voie à suivre; vous pourriez peut-être l'affiner à une requête "in", plutôt que plusieurs requêtes différentes. Ainsi, vous exécutez la logique qui détermine si un rôle user peut voir le contenu, puis exécutez une requête sur les lignes de "select * from content where content_id in (1, 3, 55)" .

Différentes personnes ont des sentiments différents sur les procédures stockées; mon avis est d'éviter d'utiliser des procédures stockées à less que vous ayez une exigence de performance prouvée et mesurable qui ne peut être satisfaite qu'en utilisant des procédures stockées. Ils sont difficiles à tester, difficiles à déboguer, il est relativement rare de find des développeurs qui sont géniaux avec Transact SQL et C # (ou autre), et le contrôle de version, etc.

Combien de nouveaux rôles par an anticipez-vous? Si peu de rôles, alors tout le code dans le code si cela rend le code plus simple. Si beaucoup, utilisez l'option # 3.

Si vous n'aimez vraiment pas les appels multiples, vous pouvez toujours faire un SELECT … UNION ou reporter la récupération à une simple procédure stockée.

Alternativement, envisagez simplement d'get l'un des frameworks de RBAC myriade et laissez-le prendre soin du problème.