首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在服务层中的blazor服务器中登录用户?

如何在服务层中的blazor服务器中登录用户?
EN

Stack Overflow用户
提问于 2022-01-26 15:11:30
回答 1查看 657关注 0票数 0

我今天问你这个问题,是因为我已经被这个问题困了一个星期了。实际上,我想使用服务层类来处理用户在我的网站上的登录和注册。寄存器部分运行良好,但登录部分不工作,因为我收到以下错误:

Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer:警告:未处理的异常呈现组件:标头是只读的,响应已经启动.

System.InvalidOperationException:头是只读的,响应已经启动.在Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowHeadersReadOnlyException() at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_SetCookie(StringValues value) at Microsoft.AspNetCore.Http.ResponseCookies.Append(String键,String value,CookieOptions options)在Microsoft.AspNetCore.Authentication.Cookies.ChunkingCookieManager.AppendResponseCookie(HttpContext上下文中,String key,String value,CookieOptions options)在Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.HandleSignInAsync(ClaimsPrincipal用户,(在Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext上下文中,字符串方案,ClaimsPrincipal主体,AuthenticationProperties属性)在Microsoft.AspNetCore.Identity.SignInManager1.SignInOrTwoFactorAsync(TUser user, Boolean isPersistent, String loginProvider, Boolean bypassTwoFactor) at Microsoft.AspNetCore.Identity.SignInManager1.PasswordSignInAsync(TUser用户),字符串密码,布尔isPersistent,布尔lockoutOnFailure)在Rpg_Agenda.Services.LoginService.LoginService1.Login(LoginModel logInInfos) in C:\Users\cleme\source\repos\Rpg\_Agenda\Rpg\_Agenda\Services\LoginService\LoginService.cs:line 41 at Rpg\_Agenda.Pages.Account.Login.LoginClicked() in C:\Users\cleme\source\repos\Rpg\_Agenda\Rpg\_Agenda\Pages\Account\Login.razor:line 42 at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at MudBlazor.MudBaseButton.OnClickHandler(MouseEventArgs ev) at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState) Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Error: Unhandled exception in circuit '2psGTBryvsuncvK6qlYQl3f4w\_cpcOsDaescmCRQRRA'. System.InvalidOperationException: Headers are read-only, response has already started. at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowHeadersReadOnlyException() at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set\_SetCookie(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.SignInManager1.SignInWithClaimsAsync(TUser用户,AuthenticationProperties authenticationProperties,IEnumerable1 additionalClaims) at Microsoft.AspNetCore.Identity.SignInManager1.SignInOrTwoFactorAsync(TUser用户,布尔isPersistent,String loginProvider,在C:\Users\cleme\source\repos\Rpg_Agenda\Rpg_Agenda\Services\LoginService\LoginService.cs:line 41 at Rpg_Agenda.Pages.Account.Login.LoginClicked() in C:\Users\cleme\source\repos\Rpg_Agenda\Rpg_Agenda\Pages\Account\Login.razor:line 42 at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task bypassTwoFactor) at MudBlazor.MudBaseButton.OnClickHandler(( Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task任务)在Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle,ComponentState owningComponentState)

在行: SignInResult signInResult =等待_signInManager.PasswordSignInAsync(user,logInInfos.Password,logInInfos.RememberMe,lockoutOnFailure: false);

如果我用用户电子邮件而不是用户对象调用PasswordSignInAsync,我也有相同的错误。

我以前尝试过使用中间件层Login,它可以工作,但我不太喜欢它在这个用例中,因为每次我需要调用调用时都会调用它。

这是我的代码:

LoginService.cs:

代码语言:javascript
运行
复制
public class LoginService<TUser> where TUser : class
{
    private readonly SignInManager<TUser> _signInManager;
    private readonly UserManager<TUser> _userManager;

    public LoginService(SignInManager<TUser> signInManager, UserManager<TUser> userManager)
    {
        _signInManager = signInManager;
        _userManager = userManager;
    }

    public async Task<bool> Login(LoginModel logInInfos)
    {
        TUser user = await _userManager.FindByEmailAsync(logInInfos.Email);
        if (user == null)
        {
            logInInfos.Error = ServiceErrors.LOGIN_WRONG_CREDENTIALS;
            return false;
        }

        if (!await _signInManager.CanSignInAsync(user))
        {
            logInInfos.Error = ServiceErrors.LOGIN_ACCOUNT_NOT_ACTIVE;
            return false;
        }

        if (!(await _signInManager.CheckPasswordSignInAsync(user, logInInfos.Password, true)).Succeeded)
        {
            logInInfos.Error = ServiceErrors.LOGIN_WRONG_CREDENTIALS;
            return false;
        }

        SignInResult signInResult = await _signInManager.PasswordSignInAsync(user, logInInfos.Password, logInInfos.RememberMe, lockoutOnFailure: false);
        if (signInResult.IsLockedOut)
        {
            logInInfos.Error = ServiceErrors.LOGIN_LOCKED_OUT;
            return false;
        }
        else if (signInResult.IsNotAllowed)
        {
            logInInfos.Error = ServiceErrors.LOGIN_NOT_ALLOWED;
            return false;
        }
        else if (!signInResult.Succeeded)
        {
            logInInfos.Error = ServiceErrors.LOGIN_ERROR;
            return false;
        }
        logInInfos.Password = null;
        return true;
    }
}

Login.razor:

代码语言:javascript
运行
复制
@page "/login"
@using Microsoft.AspNetCore.Identity
@using RpgAgenda.Data.Entities
@using Rpg_Agenda.Shared
@using Rpg_Agenda.Services.LoginService
@using Rpg_Agenda.Services.LoginService.Models

@inject LoginService<User> loginService
@inject NavigationManager NavMgr

<MudGrid Justify="Justify.Center">
    <MudItem xs="4">
        <MudPaper Class="pa-4" Elevation="3">
            <MudForm @ref="form">
                <ErrorField errorValue="@loginModel.Error"></ErrorField>

                <MudTextField T="string" Label="Email" Required="true" @ref="email" RequiredError="Email is required" />
                <MudTextField T="string" InputType="InputType.Password" Label="Password" Required="true" @ref="password" RequiredError="Password is required" />

                <div class="d-flex align-center justify-center mt-6">
                    <MudButton FullWidth="true" OnClick="LoginClicked" Variant="Variant.Filled" Color="Color.Primary">Login</MudButton>
                </div>
            </MudForm>
        </MudPaper>
    </MudItem>
</MudGrid>

@code {
    private MudTextField<string> email;
    private MudTextField<string> password;
    private MudForm form;
    private LoginModel loginModel = new LoginModel();

    private async Task LoginClicked()
    {
        await form.Validate();

        if (form.IsValid)
        {
            loginModel.Email = email.Value;
            loginModel.Password = password.Value;
            bool isLoggedIn = await loginService.Login(loginModel);
            if(isLoggedIn)
            {
                NavMgr.NavigateTo("/");
            }
        }
    }
}

Startup.cs:

代码语言:javascript
运行
复制
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddMudServices();

        services.AddDbContext<Rpg_AgendaContext>(options => options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));

        services.AddDefaultIdentity<User>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<Rpg_AgendaContext>();

        services.AddScoped<SignInManager<User>>();
        services.AddScoped<UserManager<User>>();

        services.AddScoped<LoginService<User>>();

        services.AddScoped<RegisterService<User>>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

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

        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapBlazorHub();
            endpoints.MapFallbackToPage("/_Host");
        });
    }
}

提前谢谢你帮我。

EN

回答 1

Stack Overflow用户

发布于 2022-01-27 01:20:39

你的问题最好用另一种方式来回答为什么它使用MVC风格的成员页面(脚手架页面等),许多人觉得这很烦人和不方便?

我认为您会发现html请求只是没有按照您希望的方式工作。一旦请求通过中间件,您就不能更改用户声明。

中间件可以拦截完整的请求,包括已发布的密码数据,因此我建议使用自定义URL登录。您可以捕获URL,登录客户端,然后导航到上一页。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70865707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档