AntiforgeryExtensions.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. using Microsoft.AspNetCore.Builder;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.AspNetCore.Routing;
  5. using System;
  6. using System.Linq;
  7. namespace EasyTemplate.Tool.Util
  8. {
  9. /// <summary>
  10. /// 在每次请求到达 EndpointMiddleware 之前,移除 Endpoint 的 antiforgery 相关 metadata,
  11. /// 从而避免框架检查到 antiforgery metadata 时要求 app.UseAntiforgery()。
  12. /// 注意:此方式会全局禁用基于 Endpoint metadata 的 antiforgery 要求,请确保 API 使用其他鉴权(如 JWT)。
  13. /// </summary>
  14. public static class AntiforgeryExtensions
  15. {
  16. public static IApplicationBuilder UseRemoveAntiforgeryMetadataGlobally(this IApplicationBuilder app)
  17. {
  18. return app.Use(async (context, next) =>
  19. {
  20. var endpoint = context.GetEndpoint();
  21. if (endpoint != null)
  22. {
  23. var original = endpoint.Metadata.ToArray();
  24. // 明确要移除的 antiforgery 相关类型
  25. var antiforgeryTypes = new Type[]
  26. {
  27. typeof(AutoValidateAntiforgeryTokenAttribute),
  28. typeof(ValidateAntiForgeryTokenAttribute),
  29. typeof(IgnoreAntiforgeryTokenAttribute)
  30. };
  31. var filtered = original.Where(m => !antiforgeryTypes.Any(t => t.IsInstanceOfType(m))).ToArray();
  32. var needReplace = original.Length != filtered.Length || !original.SequenceEqual(filtered);
  33. if (needReplace)
  34. {
  35. var newEndpoint = new Endpoint(endpoint.RequestDelegate, new EndpointMetadataCollection(filtered), endpoint.DisplayName);
  36. // 将新的 endpoint 设置到当前请求上下文,后续 EndpointMiddleware 会使用它
  37. context.SetEndpoint(newEndpoint);
  38. }
  39. }
  40. await next();
  41. });
  42. }
  43. // 保留一个兼容的短路方法(如果需要)
  44. public static IApplicationBuilder UseAntiforgeryValidation(this IApplicationBuilder app)
  45. {
  46. return app.Use(async (context, next) =>
  47. {
  48. var endpoint = context.GetEndpoint();
  49. if (endpoint?.Metadata?.GetMetadata<IgnoreAntiforgeryTokenAttribute>() != null)
  50. {
  51. await next();
  52. return;
  53. }
  54. var path = context.Request.Path.Value ?? string.Empty;
  55. if (path.StartsWith("/api/", StringComparison.OrdinalIgnoreCase))
  56. {
  57. await next();
  58. return;
  59. }
  60. await next();
  61. });
  62. }
  63. }
  64. }