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

.NET5多项目JWT鉴权配置及MVC调用API报500错误问题咨询

问题根因汇总
  • 三个项目的Configure方法都缺失认证授权中间件注册,认证流程根本未生效
  • JWT配置中Issuer是http://localhost:44318,但API、MVC中JWT配置的Authority写为https://localhost:44318,发行方不匹配导致令牌验证失败
  • API项目的JWT配置未指定IssuerSigningKey和完整验证规则,无法正确校验令牌签名
  • MVC项目是前端Web应用,不应该用Bearer作为默认认证方案,应该用Cookie认证存储用户身份和令牌,避免每次请求都手动传递token

各项目修正配置

1. JWT.IDP 项目

Configure方法补充中间件(ConfigureServices无需修改)

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "JWT.IDP v1"));
    }

    app.UseHttpsRedirection();
    app.UseRouting();

    // 必须按顺序加:先认证、后授权
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

确保IDP的实际访问地址和appsettings.json中JWT配置的Issuer完全一致,不要http和https混用


2. JWT.API 项目

ConfigureServices完整配置

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    // JWT认证配置
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ClockSkew = TimeSpan.FromMinutes(Convert.ToInt32(Configuration["JWT:DurationInMinutes"])),
                ValidIssuer = Configuration["JWT:Issuer"],
                ValidAudience = Configuration["JWT:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Key"]))
            };
        });
    // Swagger配置(可选新增Bearer认证支持)
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWT.API", Version = "v1" });
        c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            Description = "输入格式:Bearer {token}",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey,
            Scheme = "Bearer"
        });
        c.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
                },
                new string[]{}
            }
        });
    });
}

Configure方法配置

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "JWT.API v1"));
    }

    app.UseHttpsRedirection();
    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

API项目的appsettings.json需要新增和IDP完全一致的JWT配置段


3. JWT.MVC 项目

ConfigureServices配置

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    // MVC用Cookie作为默认认证方案,存储用户状态和令牌
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.LoginPath = "/Login/DoLogin";
            options.AccessDeniedPath = "/Home/AccessDenied";
        });
    // 注册HttpClient工厂,避免手动new HttpClient导致的资源泄漏
    services.AddHttpClient();
}

Configure方法配置

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

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

控制器代码修正

using Microsoft.AspNetCore.Authentication;
using System.Security.Claims;

namespace JWT.MVC.Controllers
{
    public class LoginController : Controller
    {
        // 注入HttpClient工厂
        private readonly IHttpClientFactory _httpClientFactory;
        public LoginController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        public IActionResult DoLogin()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DoLogin([Bind("EmailOrName,Password")] LoginRequestModel loginRequestModel)
        {
            var apiName = "https://localhost:44318/api/User/login";
            var httpClient = _httpClientFactory.CreateClient();
            HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, loginRequestModel);
            var jasonString = await response.Content.ReadAsStreamAsync();
            var data = await JsonSerializer.DeserializeAsync<IEnumerable<AccessibleDb>>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
            foreach (var item in data)
            {
                item.UserName = loginRequestModel.EmailOrName;
            }
            return View("SelectDatabase", data);
        }
      
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> PostLogin(string db, string user)
        {
            TokenRequestModel tokenRequestModel = new TokenRequestModel() { Database = db, UserName = user };
            var apiName = "https://localhost:44318/api/User/tokenonly";
            var httpClient = _httpClientFactory.CreateClient();
            HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, tokenRequestModel);
            var jasonString = await response.Content.ReadAsStreamAsync();
            var data = await JsonSerializer.DeserializeAsync<AuthenticationModel>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
            
            // 写入Cookie认证,把令牌存入用户Claim
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user),
                new Claim("Database", db),
                new Claim("AccessToken", data.Token)
            };
            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));

            ViewBag.SelectedDb = db;
            return View(data);
        }

        [Authorize] // 加认证校验,未登录自动跳转登录页
        public async Task<IActionResult> GetWeatherData()
        {
            // 从当前用户Claim中取令牌,无需手动传参
            var accessToken = User.FindFirstValue("AccessToken");
            var apiName = "https://localhost:44338/weatherforecast";
            var httpClient = _httpClientFactory.CreateClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await httpClient.GetAsync(apiName);
            if (!response.IsSuccessStatusCode)
            {
                ViewBag.Error = response.StatusCode;
                return View("Weatherdata");
            }
            var jasonString = await response.Content.ReadAsStreamAsync();
            var data = await JsonSerializer.DeserializeAsync<WeatherForecast>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
            return View("Weatherdata", data);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 16:06:04