ASP.NET Web API:处理源不允许的消息

时间:2015-01-06 19:47:58

标签: cors asp.net-web-api2

我在ASP.NET Web API项目中启用了CORS,一切都按预期工作。我想在提供无效原点时覆盖默认错误消息。现在我收到了一条默认错误消息:

{"Message":"The origin 'http://xyz' is not allowed."}

我想返回这样的内容:

{"Code": 1000, "Message":"The origin 'http://xyz' is not allowed."}

我通过自定义政策启用CORS:

config.SetCorsPolicyProviderFactory(new MyCorsPolicyProviderFactory());
config.EnableCors();

定义错误消息在哪里?任何帮助,将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:0)

我能够通过做类似以下的事情来实现这一目标:

  1. 编写自定义CorsResult以存储错误代码。
  2. public class MyCorsResult : CorsResult {
        public ErrorCode ErrorCode { get; set; }
    
        public new bool IsValid {
            get {
                return base.IsValid && ErrorCode == default(int);
            }
        }
    
    }
    
    1. 编写自定义CorsEngine并覆盖TryValidateOrigin以正确设置错误代码。
    2. public class MyCorsEngine : CorsEngine {
      
          public bool TryValidateOrigin(CorsRequestContext requestContext, CorsPolicy policy, MyCorsResult result) {
              if (requestContext == null) {
                  throw new ArgumentNullException("requestContext");
              }
              if (policy == null) {
                  throw new ArgumentNullException("policy");
              }
              if (result == null) {
                  throw new ArgumentNullException("result");
              }
              if (requestContext.Origin != null) {
                  if (policy.AllowAnyOrigin) {
                      if (policy.SupportsCredentials) {
                          result.AllowedOrigin = requestContext.Origin;
                      }
                      else {
                          result.AllowedOrigin = CorsConstants.AnyOrigin;
                      }
                  }
                  else if (policy.Origins.Contains(requestContext.Origin)) {
                      result.AllowedOrigin = requestContext.Origin;
                  }
                  else {
                      result.ErrorCode = 1000;
                      result.ErrorMessages.Add(string.Format("The origin '{0}' is not allowed", requestContext.Origin));
                  }
              }
              else {
                  result.ErrorCode = 1001;
                  result.ErrorMessages.Add("The origin header is missing");
              }
              return result.IsValid;
          }
      
          // Needed to implement the below since we're using `MyCorsResult` instead of `CorsResult` now
          public MyCorsResult EvaluatePolicy(CorsRequestContext requestContext, CorsPolicy policy) {
              if (requestContext == null) {
                  throw new ArgumentNullException("requestContext");
              }
              if (policy == null) {
                  throw new ArgumentNullException("policy");
              }
              MyCorsResult result = new MyCorsResult();
              if (this.TryValidateOrigin(requestContext, policy, result)) {
                  result.SupportsCredentials = policy.SupportsCredentials;
                  if (requestContext.IsPreflight) {
                      if (this.TryValidateMethod(requestContext, policy, result)) {
                          if (!this.TryValidateHeaders(requestContext, policy, result)) {
                              return result;
                          }
                          result.PreflightMaxAge = policy.PreflightMaxAge;
                      }
                      return result;
                  }
                  AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders);
              }
              return result;
          }
      
          private static void AddHeaderValues(IList<string> target, IEnumerable<string> headerValues) {
              foreach (string str in headerValues) {
                  target.Add(str);
              }
          }
      }
      
      1. 编写自定义CorsMessageHandler以在错误响应中包含错误代码。
      2. public class MyCorsMessageHandler : CorsMessageHandler {
        
            private HttpConfiguration _httpConfiguration;
        
            public MyCorsMessageHandler(HttpConfiguration httpConfiguration) : base (httpConfiguration) {
                _httpConfiguration = httpConfiguration;
            }
        
            public async override Task<HttpResponseMessage> HandleCorsPreflightRequestAsync(HttpRequestMessage request, CorsRequestContext corsRequestContext, CancellationToken cancellationToken) {
                HttpResponseMessage message2;
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }
                if (corsRequestContext == null)
                {
                    throw new ArgumentNullException("corsRequestContext");
                }
                try
                {
                    new HttpMethod(corsRequestContext.AccessControlRequestMethod);
                }
                catch (ArgumentException)
                {
                    return request.CreateErrorResponse(HttpStatusCode.BadRequest, "Access control request method cannot be null or empty");
                }
                catch (FormatException)
                {
                    return request.CreateErrorResponse(HttpStatusCode.BadRequest, string.Format(CultureInfo.CurrentCulture, "Invalid access control request method: '{0}'", new object[] { corsRequestContext.AccessControlRequestMethod }));
                }
                CorsPolicy corsPolicy = await this.GetCorsPolicyAsync(request, cancellationToken);
                if (corsPolicy != null)
                {
                    MyCorsResult result;
                    HttpResponseMessage response = null;
                    if (this.TryEvaluateCorsPolicy(corsRequestContext, corsPolicy, out result))
                    {
                        response = request.CreateResponse(HttpStatusCode.OK);
                        response.WriteCorsHeaders(result);
                    }
                    else
                    {
                        if (result != null) {
                            if (result.ErrorCode > 0) {
                                var content = new {
                                    code = result.ErrorCode,
                                    message = result.ErrorMessages.FirstOrDefault()
                                };
                                response = new HttpResponseMessage(HttpStatusCode.BadRequest);
                                response.Content = new ObjectContent<dynamic>(content, new JsonMediaTypeFormatter(), "application/json");
                            }
                            else {
                                response = request.CreateErrorResponse(HttpStatusCode.BadRequest, string.Join(" | ", result.ErrorMessages));
                            }
                        }
                        else {
                            response = request.CreateResponse(HttpStatusCode.BadRequest);
                        }
                    }
                    message2 = response;
                }
                else
                {
                    message2 = await base.SendAsync(request, cancellationToken);
                }
                return message2;
            }
        
            private async Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
                CorsPolicy corsPolicy = null;
                ICorsPolicyProvider corsPolicyProvider = this._httpConfiguration.GetCorsPolicyProviderFactory().GetCorsPolicyProvider(request);
                if (corsPolicyProvider == null) {
                    return corsPolicy;
                }
                return await corsPolicyProvider.GetCorsPolicyAsync(request, cancellationToken);
            }
        
            private bool TryEvaluateCorsPolicy(CorsRequestContext requestContext, CorsPolicy corsPolicy, out MyCorsResult corsResult) {
                var engine = this._httpConfiguration.GetCorsEngine() as MyCorsEngine;
                corsResult = engine.EvaluatePolicy(requestContext, corsPolicy);
                return ((corsResult != null) && corsResult.IsValid);
            }
        
        }
        
        1. 最后注册一切。
        2. config.SetCorsEngine(new MyCorsEngine());
          config.MessageHandlers.Add(new MyCorsMessageHandler(config));
          

          希望能帮助别人!