使用身份验证托管的Blazor Wasm上出现Azure 500错误 [英] Azure 500 error on a Blazor Wasm Hosted with Authentication

查看:0
本文介绍了使用身份验证托管的Blazor Wasm上出现Azure 500错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里完全不知所措。我有一个Blazor WASM托管运行.net5,它已经部署到Azure应用程序服务。当没有数据库时,部署到Azure是没有问题的。它如预期的那样装载和运行。从那以后,我安装了身份和DBContext。所有内容都在本地构建,并使用本地SQL实例正常运行。

在Azure上,我创建了一个新的SQLServer和一个SQL数据库。在SQL数据库防火墙设置中,我拥有允许Azure服务和资源访问此服务器的规则以及我的客户端IP的规则(不是Azure应用程序的IP)。

对于配置中的应用程序服务,我有一个名为DefaultConnection的ConnectionString(与appsettings.json中的相同),其连接字符串与SQLDatabase提供的源AppConfig类型SqlAzure相同

我正在使用VS2019在服务器上发布项目(启动项目)发布到Azure。我选择的Target是Azure->;Azure App Sevices(Windows)和我的实例名称。配置为版本、目标框架net5.0、部署模式框架相关、目标运行时可移植。

服务依赖项设置为AzureSqlDatabase,它使用ConnectionName DefaultConnection,用户名和密码是在Azure上创建的SQL Server的管理用户密码设置,SaveConnectionStringValue是Azure应用程序设置。(这会自动填充上述应用程序服务配置连接字符串。

当我单击发布时,我在输出中看到所有发布都正确:

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错误。

如果我返回到发布和编辑设置-数据库-DefaultConnection,并选中在运行时使用此连接字符串,选择在ServiceDependency中配置的连接字符串以及EntityFrameworkMigrations DataContext在发布时应用此迁移。当我发布该配置文件时,它将执行迁移以及我在DataContext OnModel创建覆盖中定义的种子

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分?!?

这是我在服务器项目中的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": "*"
}

以下是服务器项目的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将它们记录到数据库中。

因此,我们可以从服务器Program.cs main方法(如上)看到";启动,下一个条目来自EntityFramework模型验证。然后就出现了错误。我可以将命名空间Microsoft.AspNetCore.Hosting.Diagnostics视为异常的来源。

  1. 我试图添加Nuget引用,但没有执行任何操作

  2. 我尝试添加对已添加服务的引用。AddApplicationInsightsTelemeter();指向服务器Startup.cs ConfigureServices的引用和指向appsettings.json的ApplicationInsights InstrumentationKey(已作为变量存在于Azure中),但这没有任何作用

  3. 我添加了对的引用,并添加了

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中的.UseAzureAppServices(),但也没有成功。

我确实注意到另一条错误消息

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托管解决方案时,我已经能够将其隔离为一个问题。我的网站在从Blazor WebAssembly切换到Blazor WebAssembly之前,已经升级到.net5版本。.net5版本能够顺利部署到Azure上。在部署WebAssembly托管版本时,我收到了500个错误。因此,这与将Blazor WebAssembly托管解决方案部署到Azure有关。

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

推荐答案

使其工作的最简单方法:

将环境变量ASPNETCORE_ENVIRONMENT添加/设置为Development

...和您的托管Blazor WASM身份最终将在Azure应用程序服务中运行


如果您不想使用上面的简单方法,请执行以下操作:

  1. 按照本文生成自签名证书:

(在生成自签名证书部分中) https://gavilan.blog/2020/08/18/blazor-using-a-self-signed-certificate-for-identityserver4-in-azure-app-service/

  1. 记住您用于生成的证书的密码。
  2. 将证书放在您的项目中(例如,在服务器项目中)
  3. 将这些附加到appsettings.json文件中:

  1. 再次发布应用程序。

这篇关于使用身份验证托管的Blazor Wasm上出现Azure 500错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆