ASP.NET Core实现仅指定API生效的Azure AD令牌校验自定义认证过滤器
方案说明
可以通过自定义授权过滤器实现该需求,你仅需要给指定的API接口打上对应的特性标记即可,其余接口不会受Azure AD令牌校验逻辑影响。
实现步骤
1. 调整现有配置
你之前写的服务注册代码无需修改,保留Startup.cs中的以下配置即可:
services.AddMicrosoftIdentityWebApiAuthentication(configuration, "AzureAd");
同时移除全局授权校验的相关配置,比如不要给全局控制器添加强制授权过滤器,也不要配置默认的全局授权策略。appsettings.json中的AzureAd配置也保持你当前的写法即可。
2. 编写自定义Azure AD授权过滤器
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Options; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; public class AzureAdTokenValidateAttribute : Attribute, IAsyncAuthorizationFilter { public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { // 跳过标记了AllowAnonymous的接口 var allowAnonymous = context.ActionDescriptor.EndpointMetadata .Any(m => m.GetType() == typeof(AllowAnonymousAttribute)); if (allowAnonymous) { await Task.CompletedTask; return; } // 读取请求头的Bearer令牌 var authHeader = context.HttpContext.Request.Headers.Authorization.FirstOrDefault(); if (string.IsNullOrWhiteSpace(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { context.Result = new UnauthorizedResult(); await Task.CompletedTask; return; } var token = authHeader["Bearer ".Length..].Trim(); try { // 读取你已经配置好的JWT校验参数 var jwtOptions = context.HttpContext.RequestServices .GetRequiredService<IOptions<JwtBearerOptions>>().Value; var tokenHandler = new JwtSecurityTokenHandler(); // 执行令牌有效性校验 var claimsPrincipal = tokenHandler.ValidateToken(token, jwtOptions.TokenValidationParameters, out _); // 校验通过后将用户身份信息写入HttpContext context.HttpContext.User = claimsPrincipal; } catch { // 任何校验失败的情况直接返回401 context.Result = new UnauthorizedResult(); await Task.CompletedTask; return; } await Task.CompletedTask; } }
3. 给指定接口绑定校验逻辑
仅需要在你要做Azure AD令牌校验的单个API上添加上述过滤器的特性即可,其余接口不会触发校验:
[ApiController] [Route("api/[controller]")] public class DemoController : ControllerBase { // 仅该接口会触发Azure AD令牌校验 [HttpGet("secure-data")] [AzureAdTokenValidate] public IActionResult GetSecureData() { // 校验通过后可以直接读取Azure AD返回的用户声明 var userId = User.FindFirstValue("oid"); return Ok(new { UserId = userId, Data = "敏感数据" }); } // 该接口为公开接口,不会触发任何令牌校验 [HttpGet("public-data")] public IActionResult GetPublicData() { return Ok("公开数据"); } }
内容的提问来源于stack exchange,提问作者Developerzzz
相关产品推荐
相关产品推荐

