Saltar al contenido

JWT no se almacena en ASP.NET Core con Blazor

Investigamos en el mundo online y de esta forma traerte la respuesta a tu problema, si tienes alguna difcultad puedes dejar la duda y te contestaremos sin falta.

Solución:

¿Qué me falta para que mi usuario se autentique? ¿Microsoft.AspNetCore.Authentication.JwtBearer no maneja la parte del cliente (almacenando el token)?

los JwtBearer se ejecuta en el lado del servidor, solo validará el encabezado de autorización de la solicitud, es decir Authorization: Bearer your_access_tokeny no le importará cómo se ejecutan los códigos de WebAssembly. Por lo tanto, debe enviar la solicitud con un accessToken jwt. Dado que el tutorial sugiere que debería usar localStorage , guardemos el accessToken con localStorage .

Porque WebAssembly no tiene acceso a BOM sin embargo, necesitamos algunos códigos javascript que sirvan como pegamento. Para hacer eso, agregue un helper.js bajo la JwtAuthentication.Client/wwwroot/js/ :

var wasmHelper = ;

wasmHelper.ACCESS_TOKEN_KEY ="__access_token__";

wasmHelper.saveAccessToken = function (tokenStr) 
    localStorage.setItem(wasmHelper.ACCESS_TOKEN_KEY,tokenStr);
;

wasmHelper.getAccessToken = function () 
    return localStorage.getItem(wasmHelper.ACCESS_TOKEN_KEY);
;

Y haga referencia al guión en su JwtAuthentication.Client/wwwroot/index.html


    Loading...
    
    

Ahora, envuelvamos los códigos javascript en C #. Crea un archivo nuevo Client/Services/TokenService.cs:

public class TokenService

    public Task SaveAccessToken(string accessToken) 
        return JSRuntime.Current.InvokeAsync("wasmHelper.saveAccessToken",accessToken);
    
    public Task GetAccessToken() 
        return JSRuntime.Current.InvokeAsync("wasmHelper.getAccessToken");
    


Registre este servicio por:

// file: Startup.cs 
services.AddSingleton(myTokenService);

Y ahora podemos inyectar el TokenService dentro Login.cshtml y utilícelo para guardar el token:

@using JwtAuthentication.Client.Services
// ...
@page "/login"
// ...
@inject TokenService tokenService

// ...

@functions 
    public string Email  get; set;  = "";
    public string Password  get; set;  = "";
    public string Token  get; set;  = "";


    /// 
    /// response from server
    /// 
    private class TokenResponse
        public string Token;
    

    private async Task SubmitForm()
    
        var vm = new TokenViewModel
        
            Email = Email,
            Password = Password
        ;

        var response = await Http.PostJsonAsync("http://localhost:57778/api/Token", vm);
        await tokenService.SaveAccessToken(response.Token);
    

Supongamos que desea enviar datos dentro de FetchData.cshtml

@functions 
    WeatherForecast[] forecasts;


    protected override async Task OnInitAsync()
    
        var token = await tokenService.GetAccessToken();
        Http.DefaultRequestHeaders.Add("Authorization",String.Format("Bearer 0 ",token));
        forecasts = await Http.GetJsonAsync("api/SampleData/WeatherForecasts");
    

y el resultado será:

ingrese la descripción de la imagen aquí

Disculpas de antemano, ya que esto responde de alguna manera a una respuesta anterior, pero no tengo el representante para comentar sobre eso.

Si ayuda a alguien más que estaba buscando de manera similar una solución para usar JWT en una aplicación Blazor, encontré la respuesta de @itminus increíblemente útil, pero también me indicó otro curso.

Un problema que encontré fue que llamar FetchData.cshtml una segunda vez explotaría cuando intentara agregar el Authorization encabezado por segunda vez.

En lugar de agregar el encabezado predeterminado allí, lo agregué al singleton HttpClient después de un inicio de sesión exitoso (que creo que Blazor crea automáticamente para usted). Tan cambiante SubmitForm en Login.cshtml de la respuesta de @itminus.

    protected async Task SubmitForm()
    
        // Remove any existing Authorization headers
        Http.DefaultRequestHeaders.Remove("Authorization");

        TokenViewModel vm = new TokenViewModel()
        
            Email = Email,
            Password = Password
        ;

        TokenResponse response = await Http.PostJsonAsync("api/Token/Login", vm);

        // Now add the token to the Http singleton
        Http.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer 0 ", response.Token));
    

Luego me di cuenta de que, mientras estaba construyendo un SPA, no necesitaba persistir el token en todas las solicitudes, solo está adjunto al HttpClient.

La siguiente clase maneja el proceso de inicio de sesión en el cliente, almacenando el token JWT en local almacenamiento. Nota: Es responsabilidad del desarrollador almacenar el token JWT y pasarlo al servidor. El cliente (Blazor, Angular, etc.) no lo hace automáticamente.

public class SignInManager
    
        // Receive 'http' instance from DI
        private readonly HttpClient http;
        public SignInManager(HttpClient http)
        
            this.http = http;
        

        [Inject]
        protected LocalStorage localStorage;


        public bool IsAuthenticated()
        
            var token = localStorage.GetItem("token");

            return (token != null); 
        

        public string getToken()
        
            return localStorage.GetItem("token");
        

        public void Clear()
        
            localStorage.Clear();
        


        // model.Email, model.Password, model.RememberMe, lockoutOnFailure: false
        public async Task PasswordSignInAsync(LoginViewModel model)
        
            SearchInProgress = true;
            NotifyStateChanged();

            var result = await http.PostJsonAsync("/api/Account", model);

            if (result)// result.Succeeded
           
              _logger.LogInformation("User logged in.");

              // Save the JWT token in the LocalStorage
              // https://github.com/BlazorExtensions/Storage
              await localStorage.SetItem("token", result);


              // Returns true to indicate the user has been logged in and the JWT token 
              // is saved on the user browser
             return true;

           

        
    

// Así es como llamas a tu API web, enviándole el token JWT para // el usuario actual

public async Task> GetProfiles()
           
            SearchInProgress = true;
            NotifyStateChanged();

            var token = signInManager.getToken();
            if (token == null) 
                throw new ArgumentNullException(nameof(AppState)); //"No token";
            

            this.http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

            // .set('Content-Type', 'application/json')
            // this.http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

            Profiles = await this.http.GetJsonAsync("/api/Profiles");


            SearchInProgress = false;
            NotifyStateChanged();
         

// También debe configurar la clase de inicio en el cliente de la siguiente manera:

public void ConfigureServices(IServiceCollection services)
    
        // Add Blazor.Extensions.Storage
       // Both SessionStorage and LocalStorage are registered
       // https://github.com/BlazorExtensions/Storage
       **services.AddStorage();**

      ...
    

// En general, esto es lo que tienes que hacer con el cliente. // En el servidor, debes tener un método, digamos en el controlador de cuenta, cuya función es generar el token JWT, debes configurar el middleware JWT, para anotar tus controladores con los attribute, como por ejemplo:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]  

etcétera…

Espero que esto ayude…

Eres capaz de añadir valor a nuestro contenido asistiendo con tu experiencia en las críticas.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Respuestas a preguntas comunes sobre programacion y tecnología