J'apprends actuellement le core et le blazor asp.net, et j'ai rencontré un problème avec peu de documentation. J'ai une application Blazor côté serveur et je m'authentifie pour utiliser le stockage local et le ServerAuthenticationStateProvider. Ce code est basé sur ce guide , voici mon implémentation actuelle du fournisseur d'état:
MyAuthenticationStateProvider.cs
@page "/loginControl" @inject IAuthService AuthService @inject NavigationManager NavigationManager <AuthorizeView> <Authorized> <b>Hello, @context.User.Identity.Name!</b> <a class="ml-md-auto btn btn-primary" href="logout?returnUrl=/" target="_top">Logout</a> </Authorized> <Authorizing> <b>Authentication in progress</b> </Authorizing> <NotAuthorized> <input type="text" placeholder="Email" @bind="@email" /> <input type="password" placeholder="Password" @bind="@password" /> <button class="ml-md-auto btn btn-primary" @onclick="@createSession"> Login </button> </NotAuthorized> </AuthorizeView> @code { string email = ""; string password = ""; async void createSession() { var loginRequest = new LoginRequest { Email = email, Password = password }; await AuthService.Login(loginRequest); } }
LoginControl.cs
namespace BlazorApp { public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider { private readonly HttpClient _httpClient; private readonly ILocalStorageService _localStorage; public MyAuthenticationStateProvider(HttpClient httpClient, ILocalStorageService localStorage) { _httpClient = httpClient; _localStorage = localStorage; } public override async Task<AuthenticationState> GetAuthenticationStateAsync() { var savedToken = await _localStorage.GetItemAsync<string>("authToken"); if (string.IsNullOrWhiteSpace(savedToken)) { return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); } var user = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(savedToken), "jwt")); return new AuthenticationState(user); } public void MarkUserAsAuthenticated(string token) { var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt")); var authState = Task.FromResult(new AuthenticationState(authenticatedUser)); NotifyAuthenticationStateChanged(authState); }
Je m'attendrais à ce qu'après l' NotifyAuthenticationStateChanged(AuthState)
, mon interface utilisateur de connexion NotifyAuthenticationStateChanged(AuthState)
et le contenu <Authorized>
s'affiche. Cependant, mon interface utilisateur affiche toujours le contenu <NotAuthorized>
. Ai-je manqué quelque chose à voir avec l'envoi au thread principal? Je suis très nouveau dans tout cela, mais mon mentor a mentionné quelque chose à voir avec cela peut-être être un fil d'arrière-plan ne disant pas à l'interface utilisateur de refaire le rendu.
3 Réponses :
Vraiment simple. Tout ce que vous avez à faire est:
// Get the loginResponse LoginResponse loginResponse = await PlayerService.Login(emailAddress, password); // if the loginResponse exists if (NullHelper.Exists(loginResponse)) { // set the player player = loginResponse.Player; // Perform the Login await OnLogin.InvokeAsync(loginResponse); }
Je viens de créer un contrôle de connexion hier, alors voici quelques bonus que vous voudrez peut-être savoir:
Mon contrôle de connexion a ceci:
<Login OnLogin="LoginComplete"></Login> /// <summary> /// This method returns the LoginResponse object /// </summary> /// <param name="loginResponse"></param> private void LoginComplete(LoginResponse loginResponse) { // if the login was successful if (loginResponse.Success) { // Set the player player = loginResponse.Player; // refresh the UI this.StateHasChanged(); } }
Et dans votre contrôle pour appeler le délégué LoginResponse
StateHasChanged();
Que contient votre réponse de connexion? Je ne suis pas tout à fait sûr de ce que fait la ligne d' await OnLogin.InvokeAsync(loginresponse)
Voici le code de LoginResponse, bien que ce projet ne soit pas encore prêt à être cloné. github.com/DataJuggler/CardCounter/blob/master/Data/… Ceci est juste une classe que j'ai écrite Spécifique à BlackJack, donc après avoir connecté le joueur depuis le contrôle de connexion, je peux renvoyer une réponse avec un joueur et son solde de jetons , équilibre du marché, etc. ou une réponse échouée avec un message. Le contrôle de connexion dans le dossier des composants et la page d'index est l'endroit où se trouve tout le code qui fonctionne.
Pour répondre à votre question, voici le code du contrôle de connexion: github.com/DataJuggler/CardCounter/blob/master/Components / ... À la ligne 69 (au moment de la rédaction de cet article), la méthode HandleLogin appelle le service Player pour effectuer le login et pour renvoyer la réponse à la page d'index, vous définissez le paramètre OnLoginComplete à la ligne 279: [Parameter] public EventCallback <LoginResponse> OnLogin {get; ensemble; } Ensuite, la page Index reçoit la réponse.
Après être passé à Blazor côté client, je suis tombé sur un problème similaire et je me suis souvenu de cette réponse qui a aidé. Il semble que je puisse également utiliser les fonctions de tâche et l'interface utilisateur attendra la tâche, puis se mettra à jour en conséquence
Je me suis trompé, le blazor côté serveur implémente déjà AuthenticationStateProvider
, donc tout ce que j'ai à faire est d'implémenter quelque chose qui définit user.identity.isauthenticated
, j'utilise des cookies et un jeton pour ce faire.
Ce sont les types de réponses qui fournissent un indice, mais qui sont trop vagues pour faire avancer quoi que ce soit. Citer all I need to do is to implement something that sets the user.identity.isauthenticated
Comment faire exactement cela?
J'ai résolu le problème en redirigeant l'utilisateur avec le gestionnaire de navigation et en forçant la redirection (en faisant cela, l'application est obligée de changer le authState). Je n'ai fait cela que parce que StateChanged()
ne fonctionnait pas.
NaviMngr.NavigateTo("/", true);