31-4 Page de connexion et Local Storage
On peut maintenant basculer du côté de Blazor pour créer une page/composante de connexion!
Préparation
Afin de supporter l'authentification par API, il nous faudra deux librairies à installer (quelqu'un tient le compte des librairies installées depuis le début?):
Microsoft.AspNetCore.Components.Authorization
pour les éléments de baseBlazored.LocalStorage
permettant d'accéder facilement aulocalstorage
du navigateur sans faire usage de JavaScript directement (et donc de devoir passer par l'interop).
Installer Microsoft.AspNetCore.Components.Authorization
.
- Sous le projet
Web.Admin
->Manage NuGet Packages
- Faire une recherche pour
Microsoft.AspNetCore.Components.Authorization
- Installer la librairie dans le projet client.
Installer Blazored.LocalStorage
- Sous le projet
Web.Admin
->Manage NuGet Packages
- Faire une recherche pour
Blazored.LocalStorage
- Installer la librairie dans le projet Afmin.
Ajout de Blazored.LocalStorage
à l'injection de dépendances
Dans Program.cs
du projet ClientAdmin
:
// LocalStorage
builder.Services.AddBlazoredLocalStorage();
Créer la page de connexion
- Sous le dossier
Web.Admin/Pages
->Add
->Directory
- Nommez le dossier
Auth
- Sous
Pages/Auth
->Add
->Blazor Component
- Choisir
Page
comme type - Nommez le composant
Connexion
- Associez la route
/connexion
et mettre un titre pertinentSnowfall.Web.Admin/Pages/Auth/Connexion.razor@page "/Connexion"
<h1>Connexion</h1>
@code {
}
Créer le client AuthHttpClient
Pour communiquer avec l'API en lien avec l'authentification, on créera un client nommé AuthHttpClient
qui encapsulera la logique de communication.
- Sous le dossier
Admin/HttpClients
->Add
->Class/Interface
- Nommez la classe
AuthHttpClient
- Assignez une URL de base et injectez via le constructure le
HttpClient
Snowfall.Web.Admin/HttpClients/AuthHttpClient.cspublic class AuthHttpClient
{
private const string BaseApiUrl = "api/auth";
private readonly HttpClient _client;
public AuthHttpClient(HttpClient client)
{
_client = client;
}
} - Ajoutez une coquille de fonction
Connexion
Snowfall.Web.Admin/HttpClients/AuthHttpClient.cs//...
public async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
{
return null;
} - Assurez-vous d'ajouter le client pour qu'il soit disponible à l'injection de dépendance.
Snowfall.Web.Admin/Configurations/InjectionDependancesConfig.cs
//...
services.AddScoped<AuthHttpClient>();
//...
Créer le formulaire de connexion
Pour se connecter, on utilisera un formulaire relativement simple lié à un modèle de type ConnexionDto
.
Le formulaire n'a rien de bien particulier par rapport à ce que nous avons fait précédemment pour le CRUD
des événements. Vous pouvez donc réutiliser la coquille suivante.
@page "/connexion"
@using Microsoft.Extensions.Localization
@using Snowfall.Application.Dtos.Auth
<div class="row">
<div class="col-md-8 col-lg-4 offset-md-2 offset-lg-4">
<h1>Connexion</h1>
@if(!String.IsNullOrEmpty(_alertMessage))
{
<div class="alert alert-danger">@_alertMessage</div>
}
<EditForm Model="@_connexionDto" OnValidSubmit="@GererSubmit">
<DataAnnotationsValidator />
<div class="form-floating mb-3">
<InputText id="email" class="form-control" type="email" placeholder="Courriel" @bind-Value="_connexionDto.Email" />
<label asp-for="email">Courriel</label>
<ValidationMessage class="invalid-feedback" For="@(() => _connexionDto.Email)" />
</div>
<div class="form-floating mb-3">
<InputText id="password" class="form-control" type="password" placeholder="Mot de passe" @bind-Value="_connexionDto.Password" />
<label asp-for="password">Mot de passe</label>
<ValidationMessage class="invalid-feedback" For="@(() => _connexionDto.Password)" />
</div>
<button class="btn btn-primary" type="submit">Se connecter</button>
</EditForm>
</div>
</div>
@code {
private ConnexionDto _connexionDto = new();
private string? _alertMessage;
async Task GererSubmit()
{
}
}
Compléter le client
- Premièrement, on initialise à
null
le résultat de connexion. Il s'agira de la valeur par défaut retournée.Snowfall.Web.Admin/HttpClients/AuthHttpClient.cspublic async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
{
ResultatConnexionDto? resultatConnexionDto = null;
return resultatConnexionDto;
} - On débute l'authentification en appelant l'API, via une requête
POST
contenant le DTO de connexion.public async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
{
ResultatConnexionDto? resultatConnexionDto = null;
var response = await _client.PostAsJsonAsync(BaseApiUrl, connexionDto);
return resultatConnexionDto;
} - Si le code de retour est un code de succès, on peut lire le retour de l'API à partir de
ReadFromJasonAsync
et convertir le retour en objetResultatConnexionDto
.public async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
{
ResultatConnexionDto? resultatConnexionDto = null;
var response = await _client.PostAsJsonAsync(BaseApiUrl, connexionDto);
if (response.IsSuccessStatusCode)
{
resultatConnexionDto = await response.Content.ReadFromJsonAsync<ResultatConnexionDto>();
}
return resultatConnexionDto;
}
Appeler AuthHttpClient
lors de la connexion
- Injectez le client dans le composant
Snowfall.Web.Admin/Pages/Auth/Connexion.razor
@page "/connexion"
@using Microsoft.Extensions.Localization
@using Snowfall.Application.Dtos.Auth
@using Snowfall.Web.Admin.HttpClients
@inject AuthHttpClient AuthHttpClient - Appeler le client dans le composant et traiter le retour
Snowfall.Web.Admin/Pages/Auth/Connexion.razor
async Task GererSubmit()
{
var resultatConnexionDto = await AuthHttpClient.Connexion(_connexionDto);
if (resultatConnexionDto is not null)
{
// À faire: stocker le jeton dans le localstorage
}
} - Pour stocker le jeton dans le localstorage, on peut utiliser la librairie
Blazored.LocalStorage
installée précédemment. On doit pour ce faire injecter la dépendance associée à cette librairie.Snowfall.Web.Admin/Pages/Auth/Connexion.razor@inject ILocalStorageService LocalStorage
- Stocker le jeton dans le local storage. Pour ce faire, on peut utiliser la librairie
Blazored.LocalStorage
installée précédemment.Snowfall.Web.ClientAdmin/Pages/Auth/Connexion.razorasync Task GererSubmit()
{
var resultatConnexionDto = await AuthHttpClient.Connexion(_connexionDto);
if (resultatConnexionDto is not null)
{
await LocalStorage.SetItemAsStringAsync("authToken", resultatConnexionDto.Token);
}
} - Dans le cas d'une erreur, fort probablement pour une mauvaise combinaison de courriel/mot de passe, on affichera le message d'erreur.
Snowfall.Web.Admin/Pages/Auth/Connexion.razor
async Task GererSubmit()
{
var resultatConnexionDto = await AuthHttpClient.Connexion(_connexionDto);
if (resultatConnexionDto is not null)
{
await LocalStorage.SetItemAsStringAsync("authToken", resultatConnexionDto.Token);
}
else
{
_alertMessage = "Mauvaise combinaison de courriel et mot de passe";
}
}
Test
Si tout se passe bien jusqu'à maintenant, vous devriez pouvoir vous compléter le formulaire, cliquer sur le bouton Connexion
et le jeton devrait apparaitre dans le Local Storage
.
Et dans le cas d'une erreur...