我正在学习Server side blazor并尝试学习认证。每当我使用SignInManager.SignInAsync(.......)时,它会抛出以下异常:
System.InvalidOperationException: 无法修改响应标头,因为响应已经开始。 at Microsoft.AspNetCore.HttpSys.Internal.HeaderCollection.ThrowIfReadOnly() at Microsoft.AspNetCore.HttpSys.Internal.HeaderCollection.set_Item(String key, StringValues value) at Microsoft.AspNetCore.Http.ResponseCookies.Append(String key, String value, CookieOptions options) at Microsoft.AspNetCore.Authentication.Cookies.ChunkingCookieManager.AppendResponseCookie(HttpContext context, String key, String value, CookieOptions options) at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) at Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext context, String scheme, ClaimsPrincipal principal, AuthenticationProperties properties) at Microsoft.AspNetCore.Identity.SignInManager
1.SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable
1 additionalClaims) at GroupMembersInfo.Pages.RegisterUser.Register() in C:\my_work\Blazor_learning\GroupMembersInfo\Pages\RegisterUser.razor:line 52 at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
我认为异常是从我已经突出显示的方法中抛出的。那么我该如何解决这个问题。这里是我的代码
starup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using GroupMembersInfo.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
namespace GroupMembersInfo
{
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)
{
services.AddDbContextPool<AppDbContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("GMIDbConnection")));
services.AddIdentity<IdentityUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<AppDbContext>();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
services.AddSingleton<WeatherForecastService>();
services.ConfigureApplicationCookie(options =>
{
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = cxt =>
{
cxt.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = cxt =>
{
cxt.Response.StatusCode = 403;
return Task.CompletedTask;
};
options.Events.OnRedirectToLogout = cxt => Task.CompletedTask;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
登录组件代码
@page "/loginPage"
@using Microsoft.AspNetCore.Identity;
@using GroupMembersInfo.Data;
@inject UserManager<IdentityUser> UserManager
@inject SignInManager<IdentityUser> SignInManager
@inject NavigationManager NavigationManager
<h3>Log In</h3>
<div class="row">
<div class="col-md-12">
<EditForm Model="@RegisterUserModel" OnValidSubmit="@LogIn">
<div class="form-group">
<label>Iser Id: </label>
<input @bind-value="RegisterUserModel.Email" class="form-control" />
</div>
<div class="form-group">
<label>Password: </label>
<input @bind-value="RegisterUserModel.Password" class="form-control" />
</div>
<div class="form-group">
<button type="submit">Submit</button>
</div>
</EditForm>
</div>
</div>
@code {
public RegisterUserModel RegisterUserModel { get; set; } = new RegisterUserModel();
public async Task LogIn()
{
var user = new IdentityUser
{
UserName = RegisterUserModel.Email
};
user.PasswordHash = SignInManager.UserManager.PasswordHasher.HashPassword(user, RegisterUserModel.Password);
await SignInManager.SignInAsync(user, isPersistent: false);
NavigationManager.NavigateTo("/");
}
}