[MAJ]Valider les url
Par amethyste le Jun 22, 2007 | Dans focus | 10 retours »
La validation des saisies sur un formulaire pour contrer certaines attaques par injection de code commence à entrer dans les mœurs.
Il reste pourtant un cas auquel on ne pense pas toujours: la validation de ses url. Il s'agit pourtant d'une zone de saisie dans laquelle un utilisateur mal intentionné pourrait parfaitement faire la preuve de son imagination fertile.
Ce problème a par exemple été longuement discuté par Dino Esposito [1] qui fournit par la même occasion une classe auxiliaire qui se basant sur un fichier Xml valide automatiquement vos url.
Il existe aussi un utilitaire gratuit appelé PageMethods qui fournit une solution similaire, mais avec une approche différente. PageMethods est en fait un outil développé par Fabrice Maguerie que nous connaissons bien ici est qui est maintenant OpenSource.
Pour être honnête, l'outil de Fabrice est le seul que j'ai utilisé sérieusement, je ne me hasarderai donc pas à les comparer.
Supposons par exemple que votre page soit requêtée de la façon suivante:
Http://amethyste.com/Zorroestarrive.aspx?idCheval=45&idLasso=112
Comment être certain que le nom des paramètres sera évident à trouver même pour un développeur qui vient d'arriver dans le projet, comment être certain qu'un jour idCheval ne devienne pas malencontreusement iCheval ou bien comment faire pour remplacer idCheval par idMazzerati afin d'améliorer le standing de Zorro?
Le plus simple est de se rendre sur la page d'accueil de PageMethods [2] afin d'y télécharger la dernière version et de lancer son programme d'installation. Celui-ci installe le produit, mais aussi une documentation et des tutoriaux.
Je vous laisserai parcourir le tutoriel qui est très complet. Mais pour les plus pressés, voyons comment cela fonctionne.
Reprenons l'exemple de la page ZorroEstArrive.aspx.
Pour permettre à PageMethods de générer l'url on doit disposer d'un mécanisme qui:
• Déclare le nom des paramètres
• Déclare le type de ces paramètres (string, Int32…)
• Déclare quels sont les paramètres obligatoires
• Déclare un éventuel format (par exemple idLasso doit être au format {0000}).
• Déclare le nom de la méthode du formulaire chargée de décoder la chaîne de requête
Côté formulaire les choses se présentent ainsi:
[PageMethod] protected void LectureChaineRequete( [ParamRequired] int idCheval, [ParamName("idLasso"),ParamFormat("0000")] int codelasso ) { // traitement des paramètres ici }
L'attribut PageMethod déclare une méthode de traitement de requête. Il peut y en avoir plusieurs dans le formulaire. Cette méthode sera appelée par le framework PageMethods lors du chargement de la page.
Nous déclarons deux paramètres qui correspondent aux paramètres de la chaîne de requête: idCheval et idLasso (alias codelasso). Nous définissons donc au passage le type des paramètres (int dans notre exemple) et le nom des paramètres que l'on peut redéfinir avec l'attribut ParamName.
On peut aussi rendre obligatoire un des paramètres avec ParamRequired.
C'est très simple, rien d'autre ne va polluer votre code, PageMethods fonctionne dans les coulisses et est très peu intrusif.
Une fois PageMethods installé sur votre machine et activé dans votre projet, une classe MyPageMethods est générée (son nom est paramétrable). Elle contient le code responsable de la création des urls.
On écrirait par exemple sur la page d'appel:
this.HyperLink1.NavigateToUrl =
MyPageMethods.ZorroEstArrive.LectureChaineRequete(45,112);
Qui nous donne l'url:
Http://amethyste.com/Zorroestarrive.aspx? PageMethod=LectureChaineRequete& idCheval=45&idLasso=0112
On peut définir une méthode par défaut afin d'alléger l'url du paramètre PageMethod, mais chez moi cela plante… Ben non, il suffit de mieux lire la doc et en particulier la FAQ! En ajoutant un appel à base(true) au constructeur du formulaire, tout fonctionne.
Remarquez que l'on est totalement dans une syntaxe objet qui devrait être intuitive pour tout le monde. Et le plus important, l'appel de vos pages est parfaitement sécurisé puisque les erreurs sont détectées à la compilation.
PageMethods peut également passer des paramètres POST et prendre en charge la redirection d'url, mais je n'ai pas eu l'occasion d'essayer.
A noter pour finir que PageMethods fonctionne avec ASP 1.1 ou ASP 2.0 en C# et VB.NET. Il a paraît t'il été testé sous Mono.
Pour revenir à l'introduction de cet article, si PageMethods valide le type du paramètre (Int32, String…), il ne valide pas son contenu. Par exemple idLasso doit être compris entre N et M ou la chaîne doit avoir tel format. Dans une optique de sécurité il peut s'avérer nécessaire d'effectuer une telle validation dans la méthode d'appel.
Bibliographie
[1] Validation d'une chaîne de requête
http://msdn.microsoft.com/msdnmag/issues/07/03/CuttingEdge/default.aspx?loc=fr
[2] Page d'accueil de PageMethods
http://metasapiens.com/PageMethods
Accessoirement Fabrice, on ne dit pas An FAQ, mais A FAQ ;-)
10 commentaires
Si tu veux de l'aide pour définir une méthode par défaut et retirer le paramètre PageMethod de tes URL, n'hésite pas à me contacter. Ca ne doit pas être grand chose.
Est-ce que tu as bien mis en place ce qui est indiqué dans le (la ? les ?) FAQ ?
Cf. entrée "I have this page with page methods, can I refer to it without any parameter on the URL? Is the PageMethod parameter mandatory in URLs?"
Pour la validation des paramètres, n'hésite pas à saisir une demande dans CodePlex (http://www.codeplex.com/PageMethods/WorkItem/List.aspx)
Je dois d'ailleurs y publier les tâches que j'ai dans ma todo-list...
Est-ce que ça t'intéresse de rejoindre le projet en tant que développeur ? On recrute !
Merci pour la présentation très claire de ce merveilleux petit outil en tout cas ;-)
Fabrice
PS : je ne suis pas convaincu pour le "A FAQ". Tu as des preuves de ce que tu avances ?
tu as pensé à changer le nom de l'attribute PageMethod utilisée par ASP.NET AJAX ?
(Ou ça fout pas trop la merde ?)
C'est à Microsoft de changer le nom de l'attribut qu'ils utilisent. Ils sont arrivés après !
Hum... je viens de vérifier, et en fait l'attribut d'ASP.NET Ajax est WebMethod. Donc pas de souci. Ils ont bien fait attention à ne pas créer de conflit avec nous :-)
Sinon, le recours au namespace aurait bien sûr permis d'éviter le problème.
Fabrice
je viens de refaire des essais, le bug se produit uniquement lorsque la page hérite de BasePage (mon code de test est celui du tutoriel).
J'utilise VS 2005 US, Windows XP français avec un projet ASP qui n'est pas du WAP mais l'autre qui marche mieux et dont j'ai oublié le nom.
Sion je n'ai pas de preuves pour AN plutôt que A si ce n'est que pour moi AN devrait précéder une voyelle ou une consonne muette. Mais bon, je ne fais pas de littérature en anglais moi ;-)
Sinon, Bertrand,tu rôdes dans le coin? Y a longtemps que l'on ne t'a pas entendu ronchonner, ça nous manque ;-)))
Pour la participation aux dev, j'aimerai bien, mais je manque trop de temps en ce moment. Peut être plus tard.
Tu utilises donc le mode "site web" (nouveau avec VS 2005) plutôt que "application web" (WAP, identique à VS 2003) si je comprends bien. C'est une question de préférence personnelle, mais je trouve WAP beaucoup mieux et je dirais même plus la seule option viable parmi les deux.
je t'enoie le source complet tu pourras essayer
Du point de vue de l'ergonomie moi je supprimerai le constructeur sans paramètre. C'est déroutant en tout cas pour moi.
Par contre la FAQ ne marche pas avec IE 7.
merci
Quand quelqu'un tente de faire hériter une page de la classe BasePage dont le constructeur sans paramètre est privé, il obtient les messages d'erreur suivant à la compilation :
WAP C# : "'MetaSapiens.PageMethods.BasePage' does not contain a constructor that takes '0' arguments"
Site web VB : "Class 'SomePage' must declare a 'Sub New' because its base class 'MetaSapiens.PageMethods.BasePage' does not have an accessible 'Sub New' that can be called with no arguments.".
Site web C# : "No overload for method 'BasePage' takes '0' arguments"
Ces messages ne sont pas clairs et n'indiquent pas que la solution consiste à surcharger le constructeur dans sa propre classe...
Si jamais quelqu'un a une autre idée...
Je viens de régler le problème pour IE7. Merci.
public class TestPage:Page
{
private TestPage()
{
}
public TestPage(int i)
{
}
}
qu'est-ce qui est différent du tien?
J'ai employé une autre solution pour améliorer tout ça. J'ai remplacé la classe BasePage par les classes BasePageWithDefaultMethod et BasePageWithoutDefaultMethod.
BasePage est maintenant marquée comme [Obsolete("Use MetaSapiens.PageMethods.BasePageWithDefaultMethod or MetaSapiens.PageMethods.BasePageWithoutDefaultMethod instead.")]
cf. http://www.codeplex.com/PageMethods/WorkItem/View.aspx?WorkItemId=256918299
Laisser un commentaire
| « Le programme WER | Les problèmes de timeout en ASP » |