Question

Dans mon application typique, l'utilisateur clique sur un bouton d'une page aspx, appelle un objet métier C #, puis exécute une procédure stockée.

Les vérifications de rôles doivent-elles être effectuées en haut de la pile, au bas de la pile ou à tous les niveaux? Il semble que si un utilisateur malveillant peut invoquer une méthode, il peut invoquer n'importe quelle méthode. Par conséquent, pour une sécurité efficace, vous devez vérifier chaque méthode (ce qui représente beaucoup de code supplémentaire à écrire).

Voici une pile d'appels typique pour illustrer ma question:

Page_Load()
{
  if(p.IsInRole("Managers"))  //or equivalent attribute
  {
    AddAccount.Visible =true;
  }
}

AddAccount_OnClick()
{
  if(p.IsInRole("Managers"))  //or equivalent attribute
  {
    //Add the account
    Account.Add(...);  //and maybe another role check...
  }
}

-- TSQL doesn't understand .NET authorization, this call is in a 'trusted' subsystem
create proc Add_Account @user, @account_name
If @user in (Select user from role_table where role='manager')
-- Add the account
Était-ce utile?

La solution

À mon avis, vous devriez le placer le plus près possible des données. Plus vous êtes proche des données, mieux vous pouvez vous assurer qu'il n'est pas possible de suivre une route détournée via votre base de code pour contourner un contrôle d'accès.

Cet argument nécessiterait que des contrôles de sécurité soient placés dans la source de données elle-même, si elle la prend en charge (comme votre SGBDR préféré), ou dans la couche d'accès aux données.

Cependant, certaines contraintes de sécurité ont une forte odeur de logique d’entreprise; par exemple. " si l'utilisateur occupe ce rôle et tente de modifier des données répondant à ces spécifications, l'opération doit être autorisée; sinon pas " ;. Cela me semble être une politique et quelque chose qui appartient à la couche Business Logic d’un moteur de règles distinct.

J'ai écrit quelque chose de similaire dans le contexte de WCF il y a quelque temps .

Autres conseils

Du point de vue de la mise en œuvre, il serait préférable de mettre en œuvre les contrôles aussi loin que possible dans la pile, car il existe le plus petit nombre de fonctions nécessitant une protection, donc le plus petit nombre de choses à gâcher, et toutes les entrées de l'utilisateur passer par la couche protégée. Si votre fondation est protégée, vous n'avez pas besoin de vous soucier de tout construire sur cette base.

Cette solution présente un inconvénient évident: l’interface utilisateur n’a aucune connaissance en matière d’authentification, d’autorisation, de vérification des données et de tout le reste. Ainsi, chaque entrée descend dans la pile, peut provoquer une erreur et remonte dans la pile pour en informer l'utilisateur. Cela créerait une expérience utilisateur désagréable car les erreurs facilement détectables dans l'interface utilisateur ne le seraient qu'après avoir transmis les données aux systèmes dorsaux. En conséquence, vous ajouterez également de nombreux contrôles à l’interface utilisateur afin de donner une meilleure expérience utilisateur.

Si vous utilisez la programmation par interface, ce n'est pas un problème, car vous pouvez partager le code de vérification entre les couches de l'application. Cela vous permet en outre d’ajouter facilement du code de vérification à toutes les couches d’application, ce qui vous donnera une défense en profondeur: un bogue d’une couche d’application peut être attrapé par une autre couche. Bien sûr, si le code de vérification lui-même est erroné et que vous le partagez entre plusieurs couches d'application, le bogue et l'erreur apparaîtront probablement dans toutes les couches d'application.

Je placerais les contrôles d'accès aux rôles dans les objets métier effectuant les tâches potentiellement dangereuses / sensibles.

Ajouter la vérification de rôle à vos événements de chargement de page et de clic de bouton serait superficiel, à mon humble avis. De plus, si vous souhaitez protéger la page, protégez-la à l’aide des directives de localisation déclaratives de votre Web.config ... par exemple. mettez tous vos " admin " des pages dans un dossier séparé et protégez le dossier dans son intégralité, de manière déclarative.

Mais vous devriez toujours avoir au minimum les contrôles sur vos méthodes d'objet métier.

Vous devez le mettre au niveau de la méthode. Vous ne pouvez pas supposer que vous atteignez cette méthode d'une manière spécifique. Cette méthode peut être appelée par le gestionnaire de boutons ou en code normal à la suite de tout type de logique. Combien de fois avez-vous vu quelque chose comme ceci appeler un gestionnaire de boutons ...

private void MyBypassingCall()
{
  if( myLogic )
  {
    AddAccount_OnClick();
  }
}

Donc, le placer sur Page_Load ne suffit pas. Vous devez également vérifier comment décorer la méthode avec un PrincipalPermissionAttribute . Cela réduit beaucoup de code.

Ceci n’est qu’un commentaire anecdotique sur l’importance de valider la sécurité du côté commercial. Dans notre cas, il ne suffisait pas d'être optimiste quant aux attentes peu élevées en matière de piratage des requêtes. Nous n'avions aucune sorte de validation dans nos objets métier et nous avons été brûlés de manière inattendue. Un client a construit un script pour automatiser son utilisation de notre site. Il a fini par suivre les liens attendus dans leur script qui n'ont pas été rendus. Il a fini par corrompre les données. Pour nous, il s’agit bien entendu davantage d’un problème d’état du système et d’intégrité des données que d’une atteinte à la sécurité, mais je suppose que les deux sont vraiment applicables.

Objets métier.

Mais au moment de la construction. Laissez chaque instance capturer un rôle très spécifique.

Éditer: Plus succinct de cette façon.

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