如何在React前端与C#后端应用中限制API访问?含MSAL授权示例需求
在React+MSAL的应用中为C#后端API添加授权机制
核心思路是:React客户端通过MSAL获取后端API的访问令牌,请求API时将令牌放在请求头中;C#后端验证令牌的合法性,仅允许携带有效令牌的请求访问受保护资源。以下是具体实现步骤和示例:
React客户端:传递MSAL访问令牌到后端API
1. 初始化MSAL时配置后端API作用域
确保MSAL实例包含后端API的授权作用域(需提前在Azure AD门户中为后端API定义该作用域):
import { PublicClientApplication, InteractionRequiredAuthError } from '@azure/msal-browser'; const msalConfig = { auth: { clientId: '你的React应用客户端ID', authority: 'https://login.microsoftonline.com/你的租户ID', redirectUri: '/', }, }; // 后端API的作用域,格式为 api://{后端API客户端ID}/{自定义作用域名} const apiScopes = ['api://你的后端API客户端ID/access_as_user']; const msalInstance = new PublicClientApplication(msalConfig);
2. 封装带令牌的API调用函数
在调用后端API前,静默获取访问令牌并附加到请求头:
async function callProtectedApi(apiUrl) { try { const activeAccount = msalInstance.getActiveAccount(); if (!activeAccount) throw new Error('当前无登录用户'); // 静默获取访问令牌 const tokenResponse = await msalInstance.acquireTokenSilent({ account: activeAccount, scopes: apiScopes, }); // 发送请求时携带Bearer令牌 const response = await fetch(apiUrl, { method: 'GET', headers: { 'Authorization': `Bearer ${tokenResponse.accessToken}`, 'Content-Type': 'application/json', }, }); if (!response.ok) throw new Error('API请求失败'); return await response.json(); } catch (error) { // 处理令牌获取失败(比如需要交互登录) if (error instanceof InteractionRequiredAuthError) { await msalInstance.acquireTokenPopup({ scopes: apiScopes }); return callProtectedApi(apiUrl); // 重试请求 } throw error; } }
C#后端(ASP.NET Core):验证MSAL令牌并授权
1. 安装依赖包
通过NuGet安装Azure AD认证相关包:
dotnet add package Microsoft.Identity.Web
2. 配置认证服务
在Program.cs中添加Azure AD令牌验证配置:
var builder = WebApplication.CreateBuilder(args); // 添加Azure AD API认证服务 builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration) .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); // 添加控制器服务 builder.Services.AddControllers(); var app = builder.Build(); // 启用认证和授权中间件(顺序不能错) app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
3. 配置appsettings.json
添加Azure AD相关配置,确保与客户端和后端API的Azure AD信息一致:
{ "AzureAd": { "Instance": "https://login.microsoftonline.com/", "TenantId": "你的租户ID", "ClientId": "你的后端API客户端ID", "Audience": "api://你的后端API客户端ID" // 需与令牌的aud字段匹配 } }
4. 保护API端点
在控制器或方法上添加[Authorize]属性,限制仅认证用户可访问:
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Security.Claims; [ApiController] [Route("api/[controller]")] [Authorize] // 整个控制器的所有接口都需要授权 public class ProtectedDataController : ControllerBase { [HttpGet] public IActionResult GetUserInfo() { // 从令牌中获取当前用户信息 var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; var userName = User.FindFirst(ClaimTypes.Name)?.Value; return Ok(new { Message = "这是受保护的API数据", UserId = userId, UserName = userName }); } // 可选:验证特定作用域 [HttpGet("scope-protected")] [Authorize(Policy = "RequireAccessAsUserScope")] public IActionResult GetScopeProtectedData() { return Ok(new { Message = "该接口需要access_as_user作用域权限" }); } }
5. 可选:自定义作用域验证策略
如果需要验证请求令牌包含特定作用域,可在Program.cs中添加授权策略:
builder.Services.AddAuthorization(options => { options.AddPolicy("RequireAccessAsUserScope", policy => { policy.RequireClaim("scp", "access_as_user"); }); });
关键注意事项
- 确保Azure AD门户中,后端API已正确暴露
access_as_user作用域,且React应用已被授予该作用域的权限 - 客户端和后端的租户ID、后端API客户端ID必须完全一致
- 后端会自动验证令牌的签名、过期时间、受众等信息,无需手动处理
内容的提问来源于stack exchange,提问作者Kristen
相关产品推荐
相关产品推荐

