Blazor Wasm Aspnetcore主持了JWT授权问题

发布于 2025-01-18 14:38:46 字数 12570 浏览 2 评论 0原文

我首先关注了有关使用 Blazor Web Assembly + asp net core Web api 构建身份 API 身份验证 api 的 YouTube 视频,经过 100 个小时的研究,在尝试使用 [Authorize] 访问 API 时,我仍然无法通过“401”未经授权

我多次关注MSDN并对代码进行了多次修改。我已恢复到指南中演示的原始版本,并且仍在处理 double & 问题。根据所使用的内容对所有内容进行了三次检查。至此,我觉得API Protection现在已经完蛋了呵呵。希望有人能看到我哪里出了问题,因为我现在不知所措。

我应该通过这次尝试获取 WeatherForecast API,但它未经授权。底部错误

客户端代码:

中使用的行

        internal readonly static string s_weather = $"{ServerBaseURL}/weatherforecast";

APIEndpoints Program.cs

using Blazored.LocalStorage;
using Client;
using Client.Providers;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;


var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");

builder.Services.AddSingleton<HttpClient>();

builder.Services.AddBlazoredLocalStorage();

builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AppAuthenticationStateProvider>();

builder.Services.AddScoped<AuthenticationStateProvider>(provider
    => provider.GetRequiredService<AppAuthenticationStateProvider>());

await builder.Build().RunAsync();

AppAuthenticationStateProvider

using Microsoft.AspNetCore.Components.Authorization;
using Blazored.LocalStorage;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace Client.Providers
{
    public class AppAuthenticationStateProvider : AuthenticationStateProvider
    {
        private readonly ILocalStorageService _localStorageService;
        private readonly JwtSecurityTokenHandler jwtSecurityTokenHandler = new();


        public AppAuthenticationStateProvider(ILocalStorageService localStorageService)
        {
            _localStorageService = localStorageService;

        }


        public async override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            try
            {
                string savedToken = await _localStorageService.GetItemAsync<string>("bearerToken");
               if (string.IsNullOrWhiteSpace(savedToken))
                {
                    return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
                }
                JwtSecurityToken jwtSecurityToken = jwtSecurityTokenHandler.ReadJwtToken(savedToken);
                DateTime expiry = jwtSecurityToken.ValidTo;

                if (expiry < DateTime.UtcNow)
                {
                    await _localStorageService.RemoveItemAsync("bearerToken");
                    return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
                }

                //Get Claims from Token and Build Authenticated User Object

                var claims = ParseClaims(jwtSecurityToken);
                var user = new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt"));
                return new AuthenticationState(user);

            }
            catch (Exception)
            {
                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            }
        }

        private IList<Claim> ParseClaims(JwtSecurityToken jwtSecurityToken)
        {
            IList<Claim> claims = jwtSecurityToken.Claims.ToList();
            // Value is username
            claims.Add(new Claim(ClaimTypes.Name, jwtSecurityToken.Subject));
            return claims;

        }

        internal async Task SignIn()
        {
            string savedToken = await _localStorageService.GetItemAsync<string>("bearerToken");
            JwtSecurityToken jwtSecurityToken = jwtSecurityTokenHandler.ReadJwtToken(savedToken);
            var claims = ParseClaims(jwtSecurityToken);
            var user = new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt"));

            Task<AuthenticationState> autnentcationState = Task.FromResult(new AuthenticationState(user));
            NotifyAuthenticationStateChanged(autnentcationState);

        }

        internal void SignOut()
        {
            ClaimsPrincipal nobody = new ClaimsPrincipal(new ClaimsIdentity());
            Task<AuthenticationState> authenticationState = Task.FromResult(new AuthenticationState(nobody));
            NotifyAuthenticationStateChanged(authenticationState);

        }

    }
}

Login.Razor

@code {
    [Inject] HttpClient HttpClient {get; set; }
    [Inject] ILocalStorageService LocalStorageService { get; set; }
    [Inject] AppAuthenticationStateProvider AuthenticationStateProvider { get; set; }


    private User _userTosignin = new();
    private bool _signinSuccessful = false;
    private bool _attemptTosigninFailed = false;
   // private string _attemptTosigninFailedErrorMessage = null;

    private async Task signinUser()
    {
        _attemptTosigninFailed = false;

        HttpResponseMessage HttpResponseMessage = await HttpClient.PostAsJsonAsync(APIEndpoints.s_signin, _userTosignin);
        if (HttpResponseMessage.IsSuccessStatusCode)
        {
            string jsonWebToken = await HttpResponseMessage.Content.ReadAsStringAsync();
            await LocalStorageService.SetItemAsync("bearerToken", jsonWebToken);
            await ((AppAuthenticationStateProvider)AuthenticationStateProvider).SignIn();
            HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", jsonWebToken);
            _signinSuccessful = true;
        }
        else 
        {
         _attemptTosigninFailed = true;
        }
    }

}

FetchData.Razor 代码

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>(APIEndpoints.s_weather);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

SERVER

Program.cs

using Server.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Configuration;
using System.Text.Json.Serialization;


var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddCors(options =>
{
    options.AddPolicy("CorsPolicy",
    builder =>
    builder
    .AllowAnyOrigin()
    .AllowAnyMethod()
    .AllowAnyHeader());
});

builder.Services.AddDbContext<AppDBContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<AppDBContext>();

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))

        };
    });





// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(
     c => { 
     c.SwaggerDoc("v1", new() {  Title = "Server", Version = "v1"});
}
);

var app = builder.Build();



// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{

}

app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server v1"));

app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");


app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    app.MapControllers();
});

app.Run();

Appsettings.json

  "AllowedHosts": "*",
  "Jwt": {
    // Change Characters
    "Key": "REDACTED GUID",
    "Issuer" :  "https://localhost:5003/"
  }

WeatherController

using MM.Shared;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Server.Controllers
{
    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

APPDBCONTEXT

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using MM.Shared.Models;

namespace Server.Data
{
    public class AppDBContext : IdentityDbContext
    {
        public AppDBContext(DbContextOptions<AppDBContext> options) : base(options)
        {

        }
    }
}

SHARED Model

namespace MM.Shared
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public string? Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}

遇到错误

GET https://localhost:5003/weatherforecast net::ERR_ABORTED 401
_mono_wasm_invoke_js_with_args @ dotnet.6.0.2.6iovc50gwi.js:1
$func219 @ 00970812:0x1a0e2
$func167 @ 00970812:0xcaf7
$func166 @ 00970812:0xba0a
$func2810 @ 00970812:0xabacf
$func1615 @ 00970812:0x6f8eb
$func1613 @ 00970812:0x6f85d
$func966 @ 00970812:0x502dc
$func219 @ 00970812:0x1a0e2
$func167 @ 00970812:0xcaf7
$func166 @ 00970812:0xba0a
$func2810 @ 00970812:0xabacf
$func1615 @ 00970812:0x6f8eb
$func1619 @ 00970812:0x6ff58
$mono_wasm_invoke_method @ 00970812:0x96c9
Module._mono_wasm_invoke_method @ dotnet.6.0.2.6iovc50gwi.js:1
managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet @ managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet:19
beginInvokeDotNetFromJS @ blazor.webassembly.js:1
b @ blazor.webassembly.js:1
e.invokeMethodAsync @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
ve @ blazor.webassembly.js:1
we @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
onGlobalEvent @ blazor.webassembly.js:1
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Response status code does not indicate success: 401 (Unauthorized).
System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__13`1[[MM.Shared.WeatherForecast[], MM.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
   at Client.Pages.FetchData.OnInitializedAsync() in \CMS\Pages\FetchData.razor:line 50
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

I started by following a youtube video on building an Identity API Authentication api with Blazor web assembly + asp net core web api, 100 hours of research later and I still cannot get past the "401" Unauthorized when attempting to access API using [Authorize]

I have followed the MSDN multiple times and made many changes to the code. I have reverted back to the original version demonstrated in the guide and still dealing with the issue double & triple-checked everything against what was used. At this point, I feel that API Protection is doomed for now heh. Hopefully, someone can see where I have this wrong because I am at a loss at this point.

I should be getting the WeatherForecast API on this attempt however its unauthorized. error at the bottom

Client code :

Used line in APIEndpoints

        internal readonly static string s_weather = 
quot;{ServerBaseURL}/weatherforecast";

Program.cs

using Blazored.LocalStorage;
using Client;
using Client.Providers;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;


var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");

builder.Services.AddSingleton<HttpClient>();

builder.Services.AddBlazoredLocalStorage();

builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AppAuthenticationStateProvider>();

builder.Services.AddScoped<AuthenticationStateProvider>(provider
    => provider.GetRequiredService<AppAuthenticationStateProvider>());

await builder.Build().RunAsync();

AppAuthenticationStateProvider

using Microsoft.AspNetCore.Components.Authorization;
using Blazored.LocalStorage;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace Client.Providers
{
    public class AppAuthenticationStateProvider : AuthenticationStateProvider
    {
        private readonly ILocalStorageService _localStorageService;
        private readonly JwtSecurityTokenHandler jwtSecurityTokenHandler = new();


        public AppAuthenticationStateProvider(ILocalStorageService localStorageService)
        {
            _localStorageService = localStorageService;

        }


        public async override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            try
            {
                string savedToken = await _localStorageService.GetItemAsync<string>("bearerToken");
               if (string.IsNullOrWhiteSpace(savedToken))
                {
                    return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
                }
                JwtSecurityToken jwtSecurityToken = jwtSecurityTokenHandler.ReadJwtToken(savedToken);
                DateTime expiry = jwtSecurityToken.ValidTo;

                if (expiry < DateTime.UtcNow)
                {
                    await _localStorageService.RemoveItemAsync("bearerToken");
                    return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
                }

                //Get Claims from Token and Build Authenticated User Object

                var claims = ParseClaims(jwtSecurityToken);
                var user = new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt"));
                return new AuthenticationState(user);

            }
            catch (Exception)
            {
                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            }
        }

        private IList<Claim> ParseClaims(JwtSecurityToken jwtSecurityToken)
        {
            IList<Claim> claims = jwtSecurityToken.Claims.ToList();
            // Value is username
            claims.Add(new Claim(ClaimTypes.Name, jwtSecurityToken.Subject));
            return claims;

        }

        internal async Task SignIn()
        {
            string savedToken = await _localStorageService.GetItemAsync<string>("bearerToken");
            JwtSecurityToken jwtSecurityToken = jwtSecurityTokenHandler.ReadJwtToken(savedToken);
            var claims = ParseClaims(jwtSecurityToken);
            var user = new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt"));

            Task<AuthenticationState> autnentcationState = Task.FromResult(new AuthenticationState(user));
            NotifyAuthenticationStateChanged(autnentcationState);

        }

        internal void SignOut()
        {
            ClaimsPrincipal nobody = new ClaimsPrincipal(new ClaimsIdentity());
            Task<AuthenticationState> authenticationState = Task.FromResult(new AuthenticationState(nobody));
            NotifyAuthenticationStateChanged(authenticationState);

        }

    }
}

Login.Razor

@code {
    [Inject] HttpClient HttpClient {get; set; }
    [Inject] ILocalStorageService LocalStorageService { get; set; }
    [Inject] AppAuthenticationStateProvider AuthenticationStateProvider { get; set; }


    private User _userTosignin = new();
    private bool _signinSuccessful = false;
    private bool _attemptTosigninFailed = false;
   // private string _attemptTosigninFailedErrorMessage = null;

    private async Task signinUser()
    {
        _attemptTosigninFailed = false;

        HttpResponseMessage HttpResponseMessage = await HttpClient.PostAsJsonAsync(APIEndpoints.s_signin, _userTosignin);
        if (HttpResponseMessage.IsSuccessStatusCode)
        {
            string jsonWebToken = await HttpResponseMessage.Content.ReadAsStringAsync();
            await LocalStorageService.SetItemAsync("bearerToken", jsonWebToken);
            await ((AppAuthenticationStateProvider)AuthenticationStateProvider).SignIn();
            HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", jsonWebToken);
            _signinSuccessful = true;
        }
        else 
        {
         _attemptTosigninFailed = true;
        }
    }

}

FetchData.Razor code

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>(APIEndpoints.s_weather);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

SERVER

Program.cs

using Server.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Configuration;
using System.Text.Json.Serialization;


var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddCors(options =>
{
    options.AddPolicy("CorsPolicy",
    builder =>
    builder
    .AllowAnyOrigin()
    .AllowAnyMethod()
    .AllowAnyHeader());
});

builder.Services.AddDbContext<AppDBContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<AppDBContext>();

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))

        };
    });





// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(
     c => { 
     c.SwaggerDoc("v1", new() {  Title = "Server", Version = "v1"});
}
);

var app = builder.Build();



// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{

}

app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server v1"));

app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");


app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    app.MapControllers();
});

app.Run();

Appsettings.json

  "AllowedHosts": "*",
  "Jwt": {
    // Change Characters
    "Key": "REDACTED GUID",
    "Issuer" :  "https://localhost:5003/"
  }

WeatherController

using MM.Shared;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Server.Controllers
{
    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

APPDBCONTEXT

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using MM.Shared.Models;

namespace Server.Data
{
    public class AppDBContext : IdentityDbContext
    {
        public AppDBContext(DbContextOptions<AppDBContext> options) : base(options)
        {

        }
    }
}

SHARED Model

namespace MM.Shared
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public string? Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}

Error Encountered

GET https://localhost:5003/weatherforecast net::ERR_ABORTED 401
_mono_wasm_invoke_js_with_args @ dotnet.6.0.2.6iovc50gwi.js:1
$func219 @ 00970812:0x1a0e2
$func167 @ 00970812:0xcaf7
$func166 @ 00970812:0xba0a
$func2810 @ 00970812:0xabacf
$func1615 @ 00970812:0x6f8eb
$func1613 @ 00970812:0x6f85d
$func966 @ 00970812:0x502dc
$func219 @ 00970812:0x1a0e2
$func167 @ 00970812:0xcaf7
$func166 @ 00970812:0xba0a
$func2810 @ 00970812:0xabacf
$func1615 @ 00970812:0x6f8eb
$func1619 @ 00970812:0x6ff58
$mono_wasm_invoke_method @ 00970812:0x96c9
Module._mono_wasm_invoke_method @ dotnet.6.0.2.6iovc50gwi.js:1
managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet @ managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet:19
beginInvokeDotNetFromJS @ blazor.webassembly.js:1
b @ blazor.webassembly.js:1
e.invokeMethodAsync @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
ve @ blazor.webassembly.js:1
we @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
onGlobalEvent @ blazor.webassembly.js:1
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Response status code does not indicate success: 401 (Unauthorized).
System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__13`1[[MM.Shared.WeatherForecast[], MM.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
   at Client.Pages.FetchData.OnInitializedAsync() in \CMS\Pages\FetchData.razor:line 50
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

空城旧梦 2025-01-25 14:38:46

在fetchdata.Razor中找到了解决方案,我需要以下

[CascadingParameter] protected Task<AuthenticationState> AuthenticationState { get; set; } 

protected override async Task OnInitializedAsync()
{
    var user = (await AuthenticationState).User;

    if (user.Identity.IsAuthenticated == true)
    {
        forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>(APIEndpoints.s_weather);
    }        
}

found the solution, In FetchData.razor i needed the following

[CascadingParameter] protected Task<AuthenticationState> AuthenticationState { get; set; } 

protected override async Task OnInitializedAsync()
{
    var user = (await AuthenticationState).User;

    if (user.Identity.IsAuthenticated == true)
    {
        forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>(APIEndpoints.s_weather);
    }        
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文