.NET 6隔离模式Azure Function Swagger UI绕过认证中间件
.NET 6 隔离模式 Azure Function Swagger 认证拦截解决方案
方案1:中间件内置路径白名单(快速生效)
直接在自定义AuthenticationMiddleware的执行入口增加路径判断,匹配Swagger/OpenAPI相关路径时直接跳过JWT校验逻辑放行即可。
注意不要只匹配带swagger的路径,Microsoft.Azure.Functions.Worker.Extensions.OpenApi 会暴露三类无认证即可访问的内置端点,需要全部加入白名单:
- Swagger UI 静态资源与页面:前缀默认是
/api/swagger/ui - OpenAPI 规范文档输出地址:前缀默认是
/api/swagger.json - OpenAPI 插件、OAuth回调等附属端点:前缀默认是
/api/openapi
中间件判断代码参考:
using Microsoft.Azure.Functions.Worker.Http; using System.Net; public class AuthenticationMiddleware { private readonly FunctionExecutionDelegate _next; // 静态定义匿名访问路径前缀,大小写不敏感匹配 private static readonly string[] AnonymousPathPrefixes = { "/api/swagger", "/api/openapi" }; public AuthenticationMiddleware(FunctionExecutionDelegate next) { _next = next; } public async Task InvokeAsync(FunctionContext context) { var request = await context.GetHttpRequestDataAsync(); if (request != null) { // 命中白名单直接放行,不做认证校验 if (AnonymousPathPrefixes.Any(prefix => request.Url.AbsolutePath.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) { await _next(context); return; } // 原有JWT令牌校验逻辑 if (!request.Headers.TryGetValues("Authorization", out var authHeaders) || !authHeaders.Any()) { var unauthorizedResp = request.CreateResponse(HttpStatusCode.Unauthorized); await unauthorizedResp.WriteStringAsync("Missing authorization header"); context.GetInvocationResult().Value = unauthorizedResp; return; } // 剩余令牌签名、过期时间、受众校验逻辑... } await _next(context); } }
注意:不要尝试通过调整
ConfigureOpenApi()和中间件的注册顺序绕过拦截——隔离模式下OpenAPI的所有端点本质是内置HttpTrigger暴露的,一定会经过你注册的自定义工作者中间件,调整顺序没有效果。
方案2:特性标记匿名访问(更规范易维护)
如果后续还有其他接口需要跳过认证,硬编码路径的方式可维护性差,可以自定义AllowAnonymousAttribute特性,在中间件里同时判断:
- 当前请求路径是否命中内置OpenAPI白名单
- 当前正在执行的函数是否标记了
[AllowAnonymous]
任意条件满足就跳过认证逻辑,后续不需要认证的业务接口只需要打特性即可,不需要修改中间件代码。
特性定义和中间件判断参考:
// 自定义匿名访问标记特性 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] public class AllowAnonymousAttribute : Attribute { } // 中间件内增加特性判断逻辑 var entryPoint = context.FunctionDefinition.EntryPoint; var assembly = Assembly.LoadFrom(context.FunctionDefinition.PathToAssembly); var typeName = string.Join('.', entryPoint.Split('.')[..^1]); var methodName = entryPoint.Split('.')[^1]; var methodInfo = assembly.GetType(typeName)?.GetMethod(methodName); var allowAnonymous = methodInfo?.GetCustomAttribute<AllowAnonymousAttribute>() != null; if (pathMatched || allowAnonymous) { await _next(context); return; }
生产环境最佳实践
- 生产环境如果不需要对外暴露Swagger文档,直接在
host.json中关闭OpenAPI能力即可,无需额外配置白名单:
{ "OpenApi": { "Enable": false } }
- 若生产环境需要对内暴露Swagger,建议额外增加环境判断,只在开发、测试环境自动放行Swagger路径,生产环境访问Swagger同样需要校验令牌权限,避免接口信息泄露。
内容的提问来源于stack exchange,提问作者Vlince
相关产品推荐
相关产品推荐

