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

ASP.Net Core 3.1+Identity Server 4中JWT Bearer Token验证失效求助

解决方法:移除默认Identity UI同时让JWT Bearer认证生效

你的问题核心在于:用AddIdentity<ApplicationUser, IdentityRole>替代AddDefaultIdentity后,ASP.NET Core默认的认证方案被设置为Cookie认证,而非JWT Bearer。当API收到Authorization: Bearer请求头时,认证系统会尝试用Cookie方案验证,自然找不到用户,进而触发重定向到登录页的逻辑。

下面是具体修复步骤和修改后的完整Startup代码:

关键调整思路

  1. 全局指定默认认证方案为JWT Bearer,让[Authorize]特性优先使用令牌验证
  2. 修改Cookie认证的行为,让API在认证失败时返回401/403状态码而非重定向(符合API场景的预期)
  3. 移除不必要的Razor Pages相关配置,彻底清除默认UI的端点

修改后的Startup.cs代码

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Munchify.Web.Data;
using Munchify.Web.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using APIBackend.Web.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;

namespace APIBackend.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));

            // 添加Identity核心功能,不包含默认UI
            services.AddIdentity<ApplicationUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            // 调整Cookie认证行为:API场景下禁用重定向,返回标准HTTP状态码
            services.ConfigureApplicationCookie(options =>
            {
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    return Task.CompletedTask;
                };
                options.Events.OnRedirectToAccessDenied = context =>
                {
                    context.Response.StatusCode = StatusCodes.Status403Forbidden;
                    return Task.CompletedTask;
                };
            });

            // 配置Identity Server,绑定用户和数据库,启用API授权
            services.AddIdentityServer()
                .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

            // 设置默认认证方案为JWT Bearer,确保[Authorize]优先验证令牌
            services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddIdentityServerJwt();

            services.AddTransient<IEmailSender, EmailSender>();

            // 仅添加API控制器相关服务,移除Razor Pages(如果不需要的话)
            services.AddControllersWithViews();
            // 若项目完全不需要Razor Pages,可删除下方注释行
            // services.AddRazorPages();
        }

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

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

            app.UseRouting();

            // 严格遵循中间件顺序:认证 → IdentityServer → 授权
            app.UseAuthentication();
            app.UseIdentityServer();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller}/{action=Index}/{id?}");
                // 若删除了AddRazorPages,同步删除下方映射
                // endpoints.MapRazorPages();
            });
        }
    }
}

修改细节说明

  1. 默认认证方案指定:通过AddAuthentication设置全局默认的认证和挑战方案为JWT Bearer,确保所有带[Authorize]的控制器自动使用令牌验证。
  2. Cookie行为修正:重写Cookie认证的重定向事件,让API在认证失败时返回标准的401/403状态码,而非跳转到登录页面,符合API的无状态特性。
  3. 清理冗余配置:移除Razor Pages相关服务和端点映射,彻底清除默认Identity UI的入口。

额外验证建议

  • 确认Identity Server已正确配置API资源和范围,移动端应用请求令牌时需包含对应API的范围。
  • 用JWT解码工具验证令牌的有效性,确保aud(受众)和scope(范围)与API配置匹配。
  • 测试API调用时,确保请求头Authorization: Bearer {token}格式正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 10:12:47