.NET Core 5 Web API适配企业API网关:自定义JWT授权请求头及前端适配问题咨询
我来帮你一步步解决这个问题,分为后端API配置和前端React+MSAL适配两部分:
后端.NET Core 5 Web API配置修改
你需要调整JWT Bearer认证的令牌获取逻辑,让它从自定义的MyApp-Authorization头中提取应用自身的JWT令牌,而不是默认的Authorization头。具体修改如下:
在你的ConfigureServices方法中,找到AddJwtBearer的配置块,添加Events来指定令牌来源:
public void ConfigureServices(IServiceCollection services) { //... //Add ASP.NET Core Identity Services services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<RPToolDBContext>() .AddSignInManager<SignInManager<IdentityUser>>(); var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.Secret)); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(opt => { opt.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = key, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; // 新增:从自定义头获取JWT令牌 opt.Events = new JwtBearerEvents { OnMessageReceived = context => { // 读取MyApp-Authorization头,提取Bearer令牌 var tokenHeader = context.Request.Headers["MyApp-Authorization"].FirstOrDefault(); if (!string.IsNullOrEmpty(tokenHeader) && tokenHeader.StartsWith("Bearer ")) { context.Token = tokenHeader.Substring(7); // 去掉"Bearer "前缀 } return Task.CompletedTask; } }; }) .AddAzureAdBearer(options => Configuration.Bind("AzureAd", options)); //... // 确保授权策略使用正确的认证方案 services.AddAuthorization(options => { options.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .Build(); }); }
这样配置后,你的API就会优先从MyApp-Authorization头读取自身的JWT令牌,而网关的Authorization头会由网关自行验证,你的应用不需要处理它。
前端React+MSAL适配修改
是的,前端需要修改代码来适配这个新的请求头格式。因为MSAL默认会将获取到的令牌放在Authorization头中,现在你需要发送两个令牌:一个给网关(放在Authorization头),另一个给你的应用(放在MyApp-Authorization头)。
核心实现示例(基于@azure/msal-react和axios):
import { useMsal } from "@azure/msal-react"; import { InteractionRequiredAuthError } from "@azure/msal-browser"; import axios from "axios"; // 获取网关所需的令牌 const getGatewayToken = async (msalInstance) => { const gatewayRequest = { scopes: ["api://your-gateway-client-id/.default"] // 替换为网关的API范围 }; try { // 静默获取令牌 const response = await msalInstance.acquireTokenSilent(gatewayRequest); return response.accessToken; } catch (error) { // 静默失败则弹出登录窗口 if (error instanceof InteractionRequiredAuthError) { const response = await msalInstance.acquireTokenPopup(gatewayRequest); return response.accessToken; } throw error; } }; // 获取应用自身所需的令牌 const getAppToken = async (msalInstance) => { const appRequest = { scopes: ["api://your-app-client-id/.default"] // 替换为你的API范围 }; try { const response = await msalInstance.acquireTokenSilent(appRequest); return response.accessToken; } catch (error) { if (error instanceof InteractionRequiredAuthError) { const response = await msalInstance.acquireTokenPopup(appRequest); return response.accessToken; } throw error; } }; // 配置axios请求拦截器 const setupAxiosInterceptors = () => { const { instance } = useMsal(); axios.interceptors.request.use(async (config) => { // 获取两个令牌 const gatewayToken = await getGatewayToken(instance); const appToken = await getAppToken(instance); // 添加请求头 config.headers["Authorization"] = `Bearer ${gatewayToken}`; config.headers["MyApp-Authorization"] = `Bearer ${appToken}`; return config; }, (error) => { return Promise.reject(error); }); }; // 在应用初始化时调用拦截器配置 setupAxiosInterceptors();
注意事项:
- 确保网关和应用的令牌请求使用正确的
clientId和scopes,否则会获取到无效令牌 - 处理令牌过期、静默获取失败等异常情况,提升用户体验
- 如果你的应用和网关使用同一身份提供商(比如Azure AD),可能需要调整令牌获取的参数来区分不同的受众
内容的提问来源于stack exchange,提问作者Giox
相关产品推荐
相关产品推荐

