使用身份验证托管的Blazor Wasm上的Azure 500错误

3pvhb19x  于 2023-10-22  发布在  其他
关注(0)|答案(1)|浏览(134)

我在这里完全迷失了。我有一个运行.net5的Blazor WASM Hosted,它已部署到Azure应用服务。当没有数据库时,部署到Azure没有问题。它按预期加载并运行。我已经安装了Identity和DBContext。一切都在本地构建,并使用本地SQL示例正常运行。
在Azure上,我创建了一个新的SQLServer和一个SQL数据库。在SQL数据库防火墙设置中,我有“允许Azure服务和资源访问此服务器”以及我的客户端IP(而不是Azure应用程序的IP)的规则。
对于Configuration中的App Service,我有一个名为DefaultConnection的ConnectionString(与appsettings.json中的相同),其连接字符串与SQLDatabase提供的连接字符串相同,源AppConfig,类型为SqlAzure
我正在使用VS 2019 Publish on the Server项目(启动项目)发布到Azure。我选择目标为Azure -> Azure应用服务(Windows)和我的示例名称。配置为Release,Target Framework net5.0,DeploymentMode Framework依赖,Target runtime Portable。
服务配置设置为AzureSqlDatabase,它使用ConnectionName DefaultConnection,配置和密码是在Azure上创建的SQL Server的管理员用户密码设置,SaveConnectionStringValue是Azure应用程序设置。(此自动填充上述应用程序服务配置连接字符串。
当我点击publish时,我在输出中看到所有发布都正确:

Publish Succeeded.
Web App was published successfully http://bbqfriend.azurewebsites.net/
========== Build: 1 succeeded, 0 failed, 6 up-to-date, 0 skipped ==========
========== Publish: 1 succeeded, 0 failed, 0 skipped ==========
Installation of Web App Site extension Microsoft.AspNetCore.AzureAppServices.SiteExtension is in progress...
Restarting the Web App...
Successfully installed Web App extension Microsoft.AspNetCore.AzureAppServices.SiteExtension
Successfully restarted Web App.

但是当页面启动时,它会显示500错误。
如果我返回到Publish and Edit the settings - Database - DefaultConnection并选中Use this Connection string at runtime,选择在ServiceMigrencies中配置的connectionstring,以及在发布时应用此迁移。当我发布这个概要文件时,它将执行迁移以及我在DataContextOnModelCreating覆盖中定义的Seeds

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            #region Identity Seed
            modelBuilder.ApplyConfiguration(new ApplicationUserConfiguration());
            modelBuilder.ApplyConfiguration(new IdentityRoleConfiguration());
            modelBuilder.ApplyConfiguration(new IdentityUserRoleConfiguration());
            #endregion

            //modelBuilder.ApplyConfiguration(new CountryConfiguration());

            
        }

所以我知道连接字符串是正确的,并且有一个具有正确模型和种子数据的数据库。为什么我得了500分?!?
这是我在Server项目中的appsettings.json

{
    "ConnectionStrings": {
        "DefaultConnection": "Server=.;Database={DatabaseName};Trusted_Connection=True;MultipleActiveResultSets=true"
    },
    "IdentityServer": {
        "Clients": {
            "XXXX.Client": {
                "Profile": "IdentityServerSPA"
            }
        }
    },
    "Serilog": {
        "Using": [ "Serilog.Sinks.MSSqlServer" ],
        "MinimumLevel": {
            "Default": "Information",
            "Override": {
                "Microsoft": "Warning",
                "Microsoft.AspNetCore": "Warning",
                "Microsoft.AspNetCore.Authorization.DefaultAuthorizationService": "Warning",
                "Microsoft.EntityFrameworkCore": "Warning",
                "System": "Warning",
                "System.Net.Http.HttpClient*": "Warning",
                "IdentityServer4": "Warning",
                "Serilog.AspNetCore": "Warning"
            }
        },
        "WriteTo": [
            {
                "Name": "MSSqlServer",
                "Args": {
                    "connectionString": "DefaultConnection",
                    "sinkOptionsSection": {
                        "tableName": "Logs"
                    },
                    "columnOptionsSection": {
                        "additionalColumns": [
                            {
                                "ColumnName": "InstanceId"
                            },
                            {
                                "ColumnName": "Origin"
                            },
                            {
                                "ColumnName": "SourceContext"
                            },
                            {
                                "ColumnName": "UserId"
                            },
                            {
                                "ColumnName": "Username"
                            }
                        ],
                        "excludeAdditionalProperties": true
                    }
                }
            }
        ]
    },
    "AllowedHosts": "*"
}

下面是Server项目的Startup.cs

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //Register the Datacontext and Connection String
            services.AddDbContext<DataContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));

            services.AddDatabaseDeveloperPageExceptionFilter();

            //Sets up the default Asp.net core Identity Screens - Use Identity Scaffolding to override defaults
            services.AddDefaultIdentity<ApplicationUser>( options =>
                    {
                        options.SignIn.RequireConfirmedAccount = true;
                        options.Password.RequireDigit = true;
                        options.Password.RequireLowercase = true;
                        options.Password.RequireUppercase = true;
                        options.Password.RequiredUniqueChars = 0;
                        options.Password.RequireNonAlphanumeric = false;
                        options.Password.RequiredLength = 8;
                        options.User.RequireUniqueEmail = true;
                    })
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<DataContext>();

            //Associates the User to Context with Identity
            services.AddIdentityServer()
                .AddApiAuthorization<ApplicationUser, DataContext>( options =>
            {
                options.IdentityResources["openid"].UserClaims.Add(JwtClaimTypes.Role);
                options.ApiResources.Single().UserClaims.Add(JwtClaimTypes.Role);
            });
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove(JwtClaimTypes.Role);

            //Adds authentication handler
            services.AddAuthentication().AddIdentityServerJwt();

            //Register Repositories for Dependency Injection
            services.AddScoped<ICountryRepository, CountryRepository>();

            services.AddControllersWithViews();
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseMigrationsEndPoint();
                app.UseWebAssemblyDebugging();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            //AutoMigrates data
            //dataContext.Database.Migrate();

            app.UseHttpsRedirection();
            app.UseBlazorFrameworkFiles();
            app.UseStaticFiles();

            app.UseSerilogIngestion();
            app.UseSerilogRequestLogging();

            app.UseRouting();

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

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapControllers();
                endpoints.MapFallbackToFile("index.html");
            });
        }
    }

下面是服务器项目的Program.cs

public class Program
    {
        public static void Main(string[] args)
        {
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .Build();

            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration)
                .Enrich.WithProperty("InstanceId", Guid.NewGuid())
                .Enrich.WithProperty("Origin", "Server")
                .CreateLogger();

            try
            {
                Log.Information("Starting up");
                CreateHostBuilder(args).Build().Run();
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Application start-up failed");
            }
            finally
            {
                Log.CloseAndFlush();
            }

        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

下面是客户端项目的Program.cs

public static async Task Main(string[] args)
        {
            //Serilog 
            var levelSwitch = new LoggingLevelSwitch();
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.ControlledBy(levelSwitch)
                .Enrich.WithProperty("InstanceId", Guid.NewGuid())
                .Enrich.FromLogContext()
                .WriteTo.BrowserHttp(controlLevelSwitch: levelSwitch)
                .CreateLogger();            

            Log.ForContext<Program>().Information("Client has started");

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

            builder.Services.AddLogging(logging =>
           {
               logging.ClearProviders();
               logging.AddSerilog(dispose: true);
           });

            builder.Services.AddHttpClient("XXX.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
                .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

            // Supply HttpClient instances that include access tokens when making requests to the server project
            builder.Services.AddTransient(sp => 
                sp.GetRequiredService<IHttpClientFactory>()
                .CreateClient("XXXX.ServerAPI"));

            builder.Services.AddApiAuthorization()
                .AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();

            //Register Services
            var baseAddress = new Uri($"{builder.HostEnvironment.BaseAddress}api/");
            void RegisterTypedClient<TClient, TImplementation>(Uri apiBaseUrl)
                where TClient : class where TImplementation : class, TClient
            {
                builder.Services.AddHttpClient<TClient, TImplementation>(client => client.BaseAddress = apiBaseUrl)
                    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
            }

            RegisterTypedClient<ICountryService, CountryService>(baseAddress);

            await builder.Build().RunAsync();
        }

我确实配置了Serilog,它看起来也在工作。以下是我在服务器启动期间看到的错误消息

System.InvalidOperationException: Startup assembly Microsoft.ApplicationInsights.StartupBootstrapper failed to execute. See the inner exception for more details.
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.ApplicationInsights.StartupBootstrapper, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'Microsoft.ApplicationInsights.StartupBootstrapper, Culture=neutral, PublicKeyToken=null'
   at System.Reflection.RuntimeAssembly.InternalLoad(ObjectHandleOnStack assemblyName, ObjectHandleOnStack requestingAssembly, StackCrawlMarkHandle stackMark, Boolean throwOnFileNotFound, ObjectHandleOnStack assemblyLoadContext, ObjectHandleOnStack retAssembly)
   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, RuntimeAssembly requestingAssembly, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, AssemblyLoadContext assemblyLoadContext)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.ExecuteHostingStartups()
   --- End of inner exception stack trace ---

System.InvalidOperationException: Startup assembly DiagnosticServices.HostingStartup failed to execute. See the inner exception for more details.
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'DiagnosticServices.HostingStartup, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'DiagnosticServices.HostingStartup, Culture=neutral, PublicKeyToken=null'
   at System.Reflection.RuntimeAssembly.InternalLoad(ObjectHandleOnStack assemblyName, ObjectHandleOnStack requestingAssembly, StackCrawlMarkHandle stackMark, Boolean throwOnFileNotFound, ObjectHandleOnStack assemblyLoadContext, ObjectHandleOnStack retAssembly)
   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, RuntimeAssembly requestingAssembly, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, AssemblyLoadContext assemblyLoadContext)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.ExecuteHostingStartups()
   --- End of inner exception stack trace ---

更新我能够复制上述错误消息,并通过Serilog记录到数据库中。

因此,我们可以看到来自Server Program.cs Main方法的“Starting up”(启动)(上面),下一个条目是来自BulletyFramework Model Validation。然后是错误。我可以看到作为异常源的Microsoft.AspNetCore.Hosting.Diagnostics的空间。
1.我试图添加一个Nuget参考,但没有做什么
1.我试图添加对已添加服务的引用。AddApplicationInsightsTelemetry();将ApplicationInsights InstrumentationKey添加到appsettings.json(它已经作为变量存在于Azure中),但这没有任何作用
1.我添加了一个引用,并添加了

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>().UseAzureAppServices();
                });

根据这里找到的解决方法,https://github.com/dotnet/extensions/issues/2566没有帮助

更新第2天

添加更多信息,因为我仍然得到相同的例外。我很好奇这是否是版本之间的兼容性问题。我的应用程序是.net5,并使用.net5抢先体验在Azure上运行。
以下是我为服务器项目准备的Nuget软件包

<ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.1" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="5.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="5.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="5.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.1" />
    <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
    <PackageReference Include="Serilog.AspNetCore.Ingestion" Version="1.0.0-dev-00012" />
    <PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
    <PackageReference Include="Serilog.Sinks.MSSqlServer" Version="5.6.0" />
  </ItemGroup>

以下是客户端项目的Nuget包

<ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.1" />
    <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
    <PackageReference Include="Serilog.Sinks.BrowserHttp" Version="1.0.0-dev-00012" />
    <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
  </ItemGroup>

我试着从客户端和服务器项目中删除Serilog。我仍然得到了500。
在删除Serilog后,我尝试从https://github.com/dotnet/extensions/issues/2566使用. xmlAzureAppServices(),但也没有成功。
我注意到一个额外的错误消息

2021-01-06 19:00:38.322 +00:00 [Error] Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware: An unhandled exception has occurred while executing the request.
System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions.<>c.<AddSigningCredentials>b__10_2(IServiceProvider sp)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at ... (removed for post size)
  • 当我将我的网站部署为Blazor WebAssembly托管解决方案时,我已经能够将此隔离为一个问题。我能够得到一个版本的我的网站,这是升级到.net5 PRE切换从Blazor WebAssembly到Blazor WebAssembly托管。.net5版本能够毫无问题地部署到Azure。当部署WebAssembly托管版本时,我得到了500个错误。因此,这与将Blazor WebAssembly托管解决方案部署到Azure有关。

我还尝试创建了一个开箱即用的Blazor WebAssembly托管解决方案,没有身份验证,并将其部署到Azure。这工作没有问题。然而,当我创建一个开箱即用的Blazor WebAssembly托管身份验证(个人用户帐户存储在应用程序中)并将其部署到Azure时,它失败了500!

qyuhtwio

qyuhtwio1#

最简单的方法让它工作:
将环境变量ASPNETCORE_ENVIRONMENT添加/设置为Development

.你的托管Blazor WASMwith Identity将最终在Azure应用服务中运行
如果你不想要上面的简单方法,那么可以这样做:
1.按照本文生成自签名证书:
(in生成自签名证书部分)https://gavilan.blog/2020/08/18/blazor-using-a-self-signed-certificate-for-identityserver4-in-azure-app-service/
1.记住您用于生成的证书的密码。
1.将证书放在您的项目中(例如在服务器项目中)
1.将这些添加到appsettings.json文件中:

1.再次发布应用程序。

相关问题