【发布时间】:2021-11-11 06:58:06
【问题描述】:
我在主机上发布了我的项目。我的项目在本地系统上运行没有任何问题。
但是在主机上发布时,它会出错。我们主机的IIS版本是10。
而我的webconfig文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\LosacoWeb.Server.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
还有错误信息:
Uncaught TypeError: Cannot read properties of undefined (reading 'register')
at (index):17
/favicon.ico:1 Failed to load resource: the server responded with a status of 404 (Not Found)
dotnet.5.0.4.js:1 mono_wasm_runtime_ready fe00e07a-5519-4dfe-b35a-f867dbaf2e28
blazor.webassembly.js:1 System.Reflection.TargetInvocationException: Arg_TargetInvocationException
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.AspNetCore.Components.Authorization, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' or one of its dependencies.
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 IO_FileName_Name, Microsoft.AspNetCore.Components.Authorization, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[<Main>d__0](<Main>d__0& stateMachine)
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 at LosacoWeb.Client.Program.Main(String[] args)
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 Exception_EndOfInnerExceptionStack
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
d.printErr @ blazor.webassembly.js:1
blazor.webassembly.js:1 at Microsoft.AspNetCore.Components.WebAssembly.Hosting.EntrypointInvoker.InvokeEntrypoint(String assemblyName, String[] args)
经过一段时间检查我们的代码后,我知道我们的问题出在 JWTAuthenticationStateProvider 类中。当我们发布没有该类的网站时,我们的网站运行良好。我将该类代码添加如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;
using LosacoWeb.Client.Helpers;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.JSInterop;
namespace LosacoWeb.Client.Auth
{
public class JWTAuthenticationStateProvider : AuthenticationStateProvider, ILoginService
{
private readonly IJSRuntime js;
private readonly string TokenKey = "******";
private readonly HttpClient httpClient;
private AuthenticationState Anonymous =>
new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
public JWTAuthenticationStateProvider(IJSRuntime js, HttpClient httpClient)
{
this.js = js;
this.httpClient = httpClient;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var token = await js.GetFromLocalStorage(TokenKey);
if (string.IsNullOrEmpty(token))
{
return Anonymous;
}
return BuildAuthenticationState(token);
}
public AuthenticationState BuildAuthenticationState(string token)
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt")));
}
private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{
var claims = new List<Claim>();
var payload = jwt.Split(".")[1];
var jsonBytes = ParsBase64WithoutPadding(payload);
var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles);
if (roles != null)
{
if (roles.ToString().Trim().StartsWith("["))
{
var parsedRoles = JsonSerializer.Deserialize<string[]>(roles.ToString());
foreach (var parsedRole in parsedRoles)
{
claims.Add(new Claim(ClaimTypes.Role, parsedRole));
}
}
else
{
claims.Add(new Claim(ClaimTypes.Role, roles.ToString()));
}
keyValuePairs.Remove(ClaimTypes.Role);
}
claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())));
return claims;
}
private byte[] ParsBase64WithoutPadding(string base64)
{
switch (base64.Length % 4)
{
case 2: base64 += "=="; break;
case 3: base64 += "="; break;
}
return Convert.FromBase64String(base64);
}
public async Task Login(string token)
{
await js.SetInLocalStorage(TokenKey, token);
var authState = BuildAuthenticationState(token);
NotifyAuthenticationStateChanged(Task.FromResult(authState));
}
public async Task LogOut()
{
await js.RemoveItem(TokenKey);
httpClient.DefaultRequestHeaders.Authorization = null;
NotifyAuthenticationStateChanged(Task.FromResult(Anonymous));
}
}
}
在program.cs中:
builder.Services.AddScoped<JWTAuthenticationStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider, JWTAuthenticationStateProvider>
(provider => provider.GetRequiredService<JWTAuthenticationStateProvider>());
builder.Services.AddScoped<ILoginService, JWTAuthenticationStateProvider>
(provider => provider.GetRequiredService<JWTAuthenticationStateProvider>());
【问题讨论】:
-
本文档中提到的路径相关设置是什么:docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/…
-
您好@Steve Greene 感谢您的回复。但我们的问题并没有解决。
-
可能缺少 Microsoft.AspNetCore.Components.Authorization 的 DLL?可能值得检查此 dll 是否存在于已部署的版本中。
-
感谢@Chris Campbell 我检查了 DLL 文件,它没有任何问题。我们在 Blazor 项目中使用 Dot Net 5 版本。