You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6使用SignInManager登录报错:未注册认证处理程序

问题:.NET 6用户认证中出现"No sign-in authentication handlers are registered"错误

运行代码时遇到以下错误:

System.InvalidOperationException: No sign-in authentication handlers are registered. Did you forget to call AddAuthentication().AddCookie("Identity.Application",...)?

   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 Microsoft.AspNetCore.Identity.SignInManager`1.SignInOrTwoFactorAsync(TUser user, Boolean isPersistent, String loginProvider, Boolean bypassTwoFactor)

   at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(TUser user, String password, Boolean isPersistent, Boolean lockoutOnFailure)

   at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(String userName, String password, Boolean isPersistent, Boolean lockoutOnFailure)

   at ApplicationCore.Infrastructure.Services.IdentityService.SigninUserAsync(String userName, String password) in C:\Users\Radhoine\source\repos\ApplicationCore\ApplicationCore.Infrastructure\Services\IdentityService.cs:line 218

   at ApplicationCore.Application.Commands.Auth.AuthCommandHandler.Handle(AuthCommand request, CancellationToken cancellationToken) in C:\Users\Radhoine\source\repos\ApplicationCore\ApplicationCore.Application\Commands\Auth\AuthCommand.cs:line 32

   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)

   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)

   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)

   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)

   at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)

   at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)

   at ApplicationCore.API.Controllers.AuthController.Login(AuthCommand command) in C:\Users\Radhoine\source\repos\ApplicationCore\ApplicationCore.API\Controllers\AuthController.cs:line 23

   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()

--- End of stack trace from previous location ---

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)

   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)

   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)

   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)

   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)

   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)

   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

相关代码

program.cs中的配置

program.cs中的配置

var _key = builder.Configuration["Jwt:Key"];
var _issuer = builder.Configuration["Jwt:Issuer"];
var _audience = builder.Configuration["Jwt:Audience"];
var _expirtyMinutes = builder.Configuration["Jwt:ExpiryMinutes"];


// Configuration for token
builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
    x.RequireHttpsMetadata = false;
    x.SaveToken = true;
    x.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidAudience = _audience,
        ValidIssuer = _issuer,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_key)),
        ClockSkew = TimeSpan.FromMinutes(Convert.ToDouble(_expirtyMinutes))

    };
});


// Dependency injection with key
builder.Services.AddSingleton<ITokenGenerator>(new TokenGenerator(_key, _issuer, _audience, _expirtyMinutes));


// Include Infrastructur Dependency
builder.Services.AddInfrastructure(builder.Configuration);

IdentityService类代码

IdentityService类代码

public class IdentityService : IIdentityService
    {
        private readonly UserManager<PartenaireContact> _userManager;
        private readonly SignInManager<PartenaireContact> _signInManager;
        private readonly RoleManager<IdentityRole> _roleManager;

        public IdentityService(UserManager<PartenaireContact> userManager, SignInManager<PartenaireContact> signInManager, RoleManager<IdentityRole> roleManager)
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _roleManager = roleManager;
            _roleManager = roleManager;
        }

        

        public async Task<bool> SigninUserAsync(string userName, string password)
        {
            var result = await _signInManager.PasswordSignInAsync(userName, password, true, false);
            return result.Succeeded;

        }

    }

问题原因与解决方法

原因分析

SignInManager.PasswordSignInAsync方法默认依赖Cookie认证处理程序来创建用户会话,但你当前只配置了JWT认证,没有注册任何用于登录的Cookie认证处理器,所以抛出该错误。

两种解决思路

思路1:添加Cookie认证配置(适用于需要Cookie会话的场景)

如果你的系统需要同时支持Cookie会话和JWT认证,或者依赖SignInManager的会话管理能力,需要在AddAuthentication中添加Cookie认证配置:

// 引用命名空间
using Microsoft.AspNetCore.Authentication.Cookies;

builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; // 指定登录用的Scheme
})
.AddJwtBearer(x =>
{
    // 原JWT配置保持不变
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
    // 可根据需求配置Cookie属性
    options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
    options.Cookie.Name = "YourAppAuthCookie";
    options.LoginPath = "/auth/login"; // 未登录时的跳转路径(如果需要)
});

思路2:改用纯JWT认证流程(推荐,适用于无会话的API场景)

如果你的系统是纯API架构,不需要服务端保存用户会话,应该直接验证密码并生成JWT令牌,而不是使用SignInManager.PasswordSignInAsync(该方法是为Cookie登录设计的)。

修改IdentityService的SigninUserAsync方法:

public async Task<string> SigninUserAsync(string userName, string password)
{
    // 查找用户
    var user = await _userManager.FindByNameAsync(userName);
    if (user == null || !await _userManager.CheckPasswordAsync(user, password))
    {
        return null; // 验证失败返回null
    }

    // 收集用户声明(如角色、ID等)
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id),
        new Claim(ClaimTypes.Name, user.UserName)
    };
    var roles = await _userManager.GetRolesAsync(user);
    claims.AddRange(roles.Select(r => new Claim(ClaimTypes.Role, r)));

    // 调用你的TokenGenerator生成JWT令牌
    return _tokenGenerator.GenerateToken(claims);
}

注意:需要在IdentityService的构造函数中注入ITokenGenerator:

private readonly ITokenGenerator _tokenGenerator;

public IdentityService(UserManager<PartenaireContact> userManager, 
                       SignInManager<PartenaireContact> signInManager, 
                       RoleManager<IdentityRole> roleManager,
                       ITokenGenerator tokenGenerator)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _roleManager = roleManager;
    _tokenGenerator = tokenGenerator;
}

这样修改后,登录接口验证用户密码后直接返回JWT令牌,客户端后续请求携带令牌即可完成认证,符合纯API的JWT认证模式。


内容的提问来源于stack exchange,提问作者Rad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 03:06:39