WebBroker permet de gérer des URL dans le cadre d'une gestion de pages web ou d'API avec Delphi.
Parfois on doit protéger une partie du site web par un user / password à l'ancienne. En authentification basique l'utilisateur et le mot de passe transitent en clair (encodée en BASE64). Bien entendu si on joue à ça le minimum vital pour limiter les risques liés au mot de passe, c'est de le faire sur un site sécurisé par un certificat SSL.
L'activation de la demande d'authentification se fait en retournant un code d'erreur 401 accompagné d'un royaume et du type d'authentification.
Avec WebBroker le code suivant est à mettre dans l'action correspondant à l'URL :
Response.StatusCode := 401;
Response.Realm := 'Espace protégé';
Response.WWWAuthenticate := 'Basic';
Bien entendu il faut l'activer sur toutes les URL devant être protégées avec le même nom d'utilisateur qui sera transmis systématiquement avec chaque page une fois pris en compte.
Une fois le mot de passe rentré par l'utilisateur il sera reçu par le serveur dans Request.Authorization. Il faut donc s'assurer que cette chaîne est remplie et correspond à un vrai user/password ou retourner le code de retour 401.
Request.Authorization contient le type d'authentification demandé suivi par un espace et les informations en BASE64. Dans le cas d'une authentification basique, le nom d'utilisateur et le mot de passe sont séparés de deux points.
Basic cHNldWRvOm1vdGRlcGFzc2U=
pseudo:motdepasse
Pour l'interpréter dans Delphi il faut donc décoder la partie chiffrée et la découper ensuite selon ce qu'on attend. Une fois fait on se retrouve avec un nom d'utilisateur et un mot de passe à vérifier dans notre liste d'utilisateurs autorisés.
Le décodage base64 peut se faire avec l'unité System.NetEncoding :
UserPassword := tnetencoding.base64.decode(Request.Authorization.Substring(6));
UserPassword doit ensuite être découpée en deux ou traitée dans son intégralité selon nos besoins et contraintes.
uses
System.NetEncoding;
procedure TWebModule1.getUserPassFromAuthorizationString(Authorization: string;
var user, pass: string);
var
UserPassDecode: string;
tab: TArray<string>;
begin
UserPassDecode := tnetencoding.base64.decode(Authorization.Substring(6));
tab := UserPassDecode.Split([':']);
case length(tab) of
1:
begin
user := tab[0];
pass := '';
end;
2:
begin
user := tab[0];
pass := tab[1];
end;
else
user := '';
pass := '';
end;
end;
function TWebModule1.UserPasswordValide(Authorization: string): Boolean;
var
user, pass: string;
begin
if Authorization.isempty then
exit(false);
getUserPassFromAuthorizationString(Request.Authorization, user, pass);
// tester user/pass
result := true;
end;
procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
user, pass: string;
begin
if not UserPasswordValide(Request.Authorization) then
begin
Response.StatusCode := 401;
Response.Realm := 'Espace protégé';
Response.WWWAuthenticate := 'Basic';
exit;
end;
getUserPassFromAuthorizationString(Request.Authorization, user, pass);
Response.Content := '<html>' +
'<head><title>Application Serveur Web</title></head>' + '<body><p>' +
Request.Authorization + '</p><p>' + user + ' / ' + pass + '</p></body>' +
'</html>';
end;