在Azure API Manager中验证POST请求正文

时间:2017-12-22 08:42:52

标签: azure-api-management

我尝试在Azure API管理器中的API上设置入站策略,该策略在将POST请求体传递给后端之前验证POST请求正文中的JSON。

我应该使用JSON模式并对其进行验证(如何?)或者我是否应该编写自己的代码,使用context.Request.Body来检查请求正文中的每个字段,或者尝试使用它是完全错误的验证APIM中的请求正文,是否留给后端?

2 个答案:

答案 0 :(得分:1)

我们目前正在使用<set-body>在API操作策略中进行验证,以进行验证(并在需要时重塑主体)。在此政策中,我们收集了所有错误,然后抛出异常:

    <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 Management直接支持的JSON模式检查。在后端处理模式检查,并通过传递请求增加延迟,这对我们来说不是一个选择。

我目前正在考虑的一个选项是在API CI / CD流程中解析JSON模式,生成通用验证并在API操作策略中将其替换。

答案 1 :(得分:0)

验证有效载荷非常好。请注意,这样做需要在APIM端缓存整个请求主体,默认情况下不会这样做。策略表达式中没有JSON模式验证器,因此您必须使用手动验证。