При использовании SignInManager.SignInAsyn c (.......) под Blazor на стороне сервера, это вызывает исключение - PullRequest
2 голосов
/ 24 января 2020

Я изучаю Blazor на стороне сервера и пытаюсь научиться аутентификации. Всякий раз, когда я использую SignInManager.SignInAsyn c (.......), он выдает следующее исключение:

System.InvalidOperationException: Заголовки ответа не могут быть изменены, поскольку ответ уже запущен (Строковый ключ, строковое значение, параметры CookieOptions) в Microsoft.AspNetCore.Authentication.Cookies.ChunkingCookieManager.AppendResponseCook ie (контекст HttpContext, строковый ключ, строковое значение, параметры CookieOptions) в Microsoft. AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.HandleSignInAsyn c (пользователь ClaimsPrincipal, свойства AuthenticationProperties) в Microsoft.AspNetCore.Authentication.AuthenticationService. ipal, свойства AuthenticationProperties) в Microsoft.AspNetCore.Identity.SignInManager 1.SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable 1 дополнительные заявления) в GroupMembersInfo.Pages.RegisterUser.Register () в C: \ my_work \ Blazor_learning \ GroupMembersInra.orzor: \ строка 52 в Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion (задача-задача) в Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsyn c () * 1013- в 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("/");
    }
}

Ответы [ 2 ]

2 голосов
/ 24 января 2020

Я отредактировал свой код, как показано ниже, согласно вашему предложению, и он работал.

        await SignInManager.SignInAsync(user, isPersistent: false).ContinueWith(prop =>
        {
            NavigationManager.NavigateTo("/");
        });
1 голос
/ 24 января 2020

Проблема в следующих двух строках:

await SignInManager.SignInAsync(user, isPersistent: false);

NavigationManager.NavigateTo("/");

До завершения SignInAsyn c страница переходит на следующую страницу. Вот почему SignInAsyn c не может завершить свою работу.

Решение:

Если добавить оператор возврата перед NavigationManager.NavigateTo, это должно решить проблему.

Это связано с тем, что метод не может вернуться до завершения ожидаемой операции.

return NavigationManager.NavigateTo("/");

Надеюсь, это поможет.

...