C#中如何发送含特殊字符的HttpPost Payload以通过Azure API网关?
问题描述
客户端使用HttpClient类向部署在Azure上的.NET Core API发起POST请求,当请求Payload不含特殊字符时可成功执行,但包含%等特殊字符时,会被Azure应用网关以403 Forbidden状态码拒绝。由于无法修改Azure API网关策略,需修改POST请求内容以实现特殊字符的传输。
原客户端调用示例
using System; using System.Threading.Tasks; using System.Net.Http; using Newtonsoft.Json; class Program { static void Main(string[] args) { Task.Run(() => MainAsync()); Console.ReadLine(); } static async Task MainAsync() { using (var client = new HttpClient()) { client.BaseAddress = new Uri("https://postCallPoc.net"); var emp = new Employee() { Name = "Jhon", Address = "%House no 20, near Clutch & Gair showroom Mumbai", DOJ = DateTime.Now.Date, Note = "%Verificaion Pending" }; var httpContent = GetSerializeContent(emp); var result = await client.PostAsync("/api/Employee/add", httpContent); Console.WriteLine(result.StatusCode); // 返回Forbidden } } public class Employee { public int? ID { get; set; } public string Name { get; set; } public string Address { get; set; } public DateTime DOJ { get; set; } public string Note { get; set; } } }
原HTTP内容创建方法
private StringContent GetSerializeContent(dynamic content) { var serilizedContent = JsonConvert.SerializeObject(content); var result = new StringContent(serilizedContent, System.Text.Encoding.UTF8); result.Headers.ContentType = new MediaTypeHeaderValue("application/json"); return result; }
原API控制器
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using DA.Common.Master; using DataEntity; using ApiCommon; using Common; namespace MasterData.Controllers { [ApiController] [Route("api/[controller]/[action]")] [Consumes("application/json")] [Produces("application/json")] public class EmployeeController : ControllerBase { ILogger<EmployeeController> _logger; public EmployeeController(ILogger<EmployeeController> logger) { _logger = logger; } [HttpPost] public ActionResult<ApiResponse> Add(Employee emp) { ApiResponse response; try { var dbResponce = EmpoyeeBal.Insatnce.Save(emp); response = new ApiResponse { Data = dbResponce }; return Ok(response); } catch (Exception ex) { _logger.Log(ex); } return BadRequest(); } } }
原错误信息
403 Forbidden
403 Forbidden
Microsoft-Azure-Application-Gateway/v2
解决方案
Azure应用网关的WAF(Web应用防火墙)会将%这类字符识别为潜在的URL注入风险,从而拦截请求。由于无法修改网关策略,可通过Base64编码特殊字符字段的方式绕过检测,在API端再解码还原内容。
修改后的客户端内容序列化方法
对包含特殊字符的字段单独进行Base64编码:
using System.Text; private StringContent GetSerializeContent(Employee content) { // 对含特殊字符的字符串字段进行Base64编码 if (!string.IsNullOrEmpty(content.Address)) { content.Address = Convert.ToBase64String(Encoding.UTF8.GetBytes(content.Address)); } if (!string.IsNullOrEmpty(content.Note)) { content.Note = Convert.ToBase64String(Encoding.UTF8.GetBytes(content.Note)); } var serializedContent = JsonConvert.SerializeObject(content); var result = new StringContent(serializedContent, Encoding.UTF8); result.Headers.ContentType = new MediaTypeHeaderValue("application/json"); return result; }
修改后的API控制器Add方法
在处理请求前对编码后的字段进行Base64解码:
using System.Text; [HttpPost] public ActionResult<ApiResponse> Add(Employee emp) { ApiResponse response; try { // 解码Base64格式的字段 if (!string.IsNullOrEmpty(emp.Address)) { emp.Address = Encoding.UTF8.GetString(Convert.FromBase64String(emp.Address)); } if (!string.IsNullOrEmpty(emp.Note)) { emp.Note = Encoding.UTF8.GetString(Convert.FromBase64String(emp.Note)); } var dbResponse = EmpoyeeBal.Insatnce.Save(emp); response = new ApiResponse { Data = dbResponse }; return Ok(response); } catch (Exception ex) { _logger.Log(ex); return StatusCode(500, "服务器内部错误"); } }
关键说明
- Base64编码会将特殊字符转换为网关允许的安全字符,避免WAF误判
- 仅针对含特殊字符的字段编码,而非整个Payload,减少不必要的性能开销
- 客户端和服务端需统一使用UTF-8编码,确保解码后内容正确
内容的提问来源于stack exchange,提问作者Neeraj Kumar Gupta
相关产品推荐
相关产品推荐

