在 Azure API 管理器中验证 POST 请求正文
Posted
技术标签:
【中文标题】在 Azure API 管理器中验证 POST 请求正文【英文标题】:Validate POST request body in Azure API Manager 【发布时间】:2017-12-22 08:42:51 【问题描述】:我正在尝试在 Azure API Manager 中的 API 上设置入站策略,该策略在将 POST 请求正文中的 JSON 传递到后端之前对其进行验证。
我应该使用 JSON 模式并对此进行验证(如何?)还是应该编写自己的代码,使用 context.Request.Body 来检查请求正文中的每个字段,或者尝试这样做是完全错误的在 APIM 中验证请求正文,应该留给后端吗?
【问题讨论】:
我也在努力实现这一目标,我还为此向微软提出了支持。您解决了这个问题还是介于两者之间? 【参考方案1】:我们目前正在 API 操作策略中使用 <set-body>
进行验证(并在需要时重新调整正文)。在此政策中,我们收集所有错误,然后抛出异常:
<set-body>@
var body = context.Request.Body.As<JObject>(true);
string businessSystemID = context.Request.Headers.GetValueOrDefault("SenderBusinessSystemID", "");
var result = new JObject();
string cleanUp = body.ToString().Replace("\r\n","");
var root = JObject.Parse(cleanUp);
var valid = false;
var errors = new JArray();
var returnValue = new JObject();
returnValue["errors"] = errors;
if(root["CostAllocation"] != null)
if(businessSystemID != string.Empty)
root["CostAllocation"]["SenderBusinessSystemID"] = businessSystemID;
if(root["CostAllocation"]["ReferenceID"] != null)
var referenceIDValidator = @"^[A-Z0-9]0,35$";
var referenceID = root["CostAllocation"]["ReferenceID"];
valid = new Regex(referenceIDValidator, RegexOptions.IgnoreCase).Match(referenceID.ToString()).Success;
if(!valid)
var error = new JObject();
error["property"] = "ReferenceID";
error["validator"] = referenceIDValidator;
error["value"] = referenceID;
error["message"] = "No valid 'ReferencedId'";
errors.Add(error);
if(root["CostAllocation"]["UserID"] != null)
var userIDValidator = @"^[\w]4,12$";
var userID = root["CostAllocation"]["UserID"];
valid = new Regex(userIDValidator, RegexOptions.IgnoreCase).Match(userID.ToString()).Success;
if(!valid)
var error = new JObject();
error["property"] = "UserID";
error["validator"] = userIDValidator;
error["value"] = userID;
error["message"] = "No valid 'UserID'";
errors.Add(error);
...
if(errors.Count > 0)
throw new Exception(returnValue.ToString());
return root.ToString(Newtonsoft.Json.Formatting.None);
</set-body>
异常在<on-error>
中被捕获、处理和格式化:
<on-error>
<choose>
<when condition="@(context.LastError.Message.Contains("Expression evaluation failed")==true)">
<set-status code="400" reason="Bad request" />
</when>
<otherwise>
<set-status code="500" reason="Error" />
</otherwise>
</choose>
<set-body template="none">@
return context.LastError.Message.Replace("Expression evaluation failed.","").Trim();
</set-body>
<base />
</on-error>
我们知道这种方法的编码工作量很大,因此我们更愿意在 API 管理中直接支持原生的 JSON 模式检查。在后端处理模式检查并通过传递请求增加延迟不是我们的选择。
我目前正在考虑的一个选项是在 API CI/CD 过程中解析 JSON 模式,生成通用验证并在 API 操作策略中替换它。
【讨论】:
有什么方法可以在我们可以用来清理这些属性的策略表达式中使用任何其他命名空间,例如 Microsoft.Security.Application.Sanitizer?根据这篇文章(docs.microsoft.com/en-us/azure/api-management/…),.net 类型仅限于此页面上的列表。 我不这么认为。 APIM 策略的运行时环境是盒装环境。【参考方案2】:验证有效载荷非常好。请注意,这样做需要在 APIM 端缓存整个请求主体,默认情况下不会这样做。 JSON 模式验证器在策略表达式中不可用,因此您必须求助于手动验证。
【讨论】:
所以,在查询中验证更好/更容易,但我真的不想将该数据放入查询参数中,如果他们在您选择 POST 时提供 UI 选项会很好.以上是关于在 Azure API 管理器中验证 POST 请求正文的主要内容,如果未能解决你的问题,请参考以下文章
Azure API 管理 - 与底层服务进行身份验证和授权同步
使用 Azure AD 通过 OAuth2 对 Azure API 管理进行身份验证