C# 如果EnableCors源代码无效,则阻止Web API执行

C# 如果EnableCors源代码无效,则阻止Web API执行,c#,asp.net-mvc,asp.net-web-api,cors,C#,Asp.net Mvc,Asp.net Web Api,Cors,我正在为我的webapi调用使用Microsofts EnableCors属性。客户端行为如我所期望的那样运行:例如,当源代码无效时,调用返回失败 但是,当我在方法内部放置断点时&从无效的源调用……该方法仍然自上而下执行(即使客户端得到失败的结果)。如果源代码无效,我根本不希望它执行 我的问题是: 如果EnableCors源代码无效,如何阻止Web API方法执行 帮我欧比-万·克诺比…你是我唯一的希望 我的代码看起来像: [HttpPost] [EnableCors(origins: "www

我正在为我的
webapi
调用使用
Microsofts EnableCors
属性。客户端行为如我所期望的那样运行:例如,当源代码无效时,调用返回失败

但是,当我在方法内部放置断点时&从无效的源调用……该方法仍然自上而下执行(即使客户端得到失败的结果)。如果源代码无效,我根本不希望它执行

我的问题是:
如果EnableCors源代码无效,如何阻止Web API方法执行

帮我欧比-万·克诺比…你是我唯一的希望

我的代码看起来像:

[HttpPost]
[EnableCors(origins: "www.zippitydoodah.com", headers: "*", methods: "*")]
public HttpResponseMessage Enqueue(HttpRequestMessage request)
{
    // NONE OF THIS SHOULD RUN: If the Origin is bad...but (oddly) it is
    TraceHandler.TraceIn(TraceLevel.Info);

    string claimId = string.Empty;
    ClaimMessage claimMessage = null;

    try 
    {
        claimId = GetClaimId(request);
        claimMessage = CreateClaimMessage(claimId, segmentClaimFullName);

        Enqueue(claimMessage);

        TraceHandler.TraceAppend(FORMAT_ENQUEUED_SUCCESS, claimId);
    }
    catch (Exception ex)
    {
        TraceHandler.TraceError(ex);
        TraceHandler.TraceOut();

        EnqueueToPoison(ex, claimMessage);
        return Request.CreateResponse(HttpStatusCode.InternalServerError, GetHttpError());
    }

    TraceHandler.TraceOut();
    return Request.CreateResponse(HttpStatusCode.OK, string.Format(FORMAT_ENQUEUED_SUCCESS, claimId));
}
我的配置看起来像:

public static class WebApiConfig
{
    #region <Methods>

    public static void Register(HttpConfiguration config)
    {
        // ENABLE CORS
        config.EnableCors();

        // CREATE ROUTES
        config.Routes.MapHttpRoute(
            name: "DefaultRpcApiActions",
            routeTemplate: "api/{controller}/actions/{action}/{id}",
            defaults: new { id = RouteParameter.Optional });

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional });
    }

    #endregion
}
公共静态类WebApiConfig
{
#区域
公共静态无效寄存器(HttpConfiguration配置)
{
//启用CORS
config.EnableCors();
//创建路线
config.Routes.MapHttpRoute(
名称:“DefaultRpcApiActions”,
routeTemplate:“api/{controller}/actions/{action}/{id}”,
默认值:new{id=RouteParameter.Optional});
config.Routes.MapHttpRoute(
名称:“DefaultApi”,
routeTemplate:“api/{controller}/{id}”,
默认值:new{id=RouteParameter.Optional});
}
#端区
}
事实证明

CORS头不应阻止对控制器MVC或Web API的调用。它只是防止结果返回到浏览器。不管发生什么,它都会被执行的方法…所以你必须阻止通过其他方式执行

还有什么意思?
您可能可以使用
authorized属性
执行此操作。但是我想在操作级别执行,所以我选择了一个
ActionFilterAttribute
,并在
OnActionExecuting

使用说明:ActionFilterAttribute

  • 继续向所有人开放CORS,然后通过行动进行限制(这样每个人都可以PING)

  • 假设所有呼叫都来自有效的
    推荐人

这意味着像从数据库调用
sqlclr
之类的东西(我正在做的事情)将不起作用,因为
referer
为空(因此,我稍后将发布一个更好的解决方案)

  • ICorsPolicyProvider
    是无用的-我正在删除它(但包括在这里)
我看到的所有示例都包括它,但我还没有找到调用它的场景。我的构造函数已经创建了
CorsPolicy
&该策略在整个调用生命周期中都是可用的……因此
ICorsPolicyProvider
方法(目前)似乎毫无用处

  • TraceHandler
    实现是我自己的-继续吧,用你自己的来代替

  • 必须添加
    Access Control Allow Origin
    头,以确保某些客户端的预期返回消息行为

下面是代码:ActionFilterAttribute

namespace My.Application.Security
{
    using My.Application.Diagnostics;
    using System;
    using System.Configuration;
    using System.Diagnostics;
    using System.Net;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Cors;
    using System.Web.Http.Controllers;
    using System.Web.Http.Cors;
    using System.Web.Http.Filters;

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class EnableWebApiCorsFromAppSettingsAttribute : ActionFilterAttribute, ICorsPolicyProvider
    {
        #region <Fields & Constants>

        private const string EXCEPTION_CONTEXT_NULL = "Access Denied: HttpActionContext cannot be null.";
        private const string EXCEPTION_REFERRER_NULL = "Access Denied: Referrer cannot be null.";
        private const string FORMAT_INVALID_REFERRER = "Access Denied: '{0}' is not a valid referrer.";
        private const string FORMAT_REFERRER = "Referrer: '{0}' was processed for this request.";
        private const string FORMAT_REFERRER_FOUND = "Referrer IsFound: {0}.";

        private readonly CorsPolicy policy;

        #endregion

        #region <Constructors>

        public EnableWebApiCorsFromAppSettingsAttribute(string appSettingKey, bool allowAnyHeader = true, bool allowAnyMethod = true, bool supportsCredentials = true)
        {
            policy = new CorsPolicy();
            policy.AllowAnyOrigin = false;
            policy.AllowAnyHeader = allowAnyHeader;
            policy.AllowAnyMethod = allowAnyMethod;
            policy.SupportsCredentials = supportsCredentials;

            SetValidOrigins(appSettingKey);

            if (policy.Origins.Count == 0)
                policy.AllowAnyOrigin = true;
        }

        #endregion

        #region <Methods>

        #region public

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            TraceHandler.TraceIn(TraceLevel.Info);

            if (actionContext == null)
                throw new ArgumentNullException("HttpActionContext");

            if (actionContext.Request.Headers.Referrer == null)
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, EXCEPTION_REFERRER_NULL);

            var referrer = actionContext.Request.Headers.Referrer.ToString();

            TraceHandler.TraceAppend(string.Format(FORMAT_REFERRER, referrer));

            // If no Origins Are Set - Do Nothing
            if (policy.Origins.Count > 0)
            {
                var isFound = policy.Origins.Contains(referrer);

                TraceHandler.TraceAppend(string.Format(FORMAT_REFERRER_FOUND, isFound));

                if (!isFound)
                {
                    TraceHandler.TraceAppend("IsFound was FALSE");
                    actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, string.Format(FORMAT_INVALID_REFERRER, referrer));
                }
            }

            TraceHandler.TraceOut();
            base.OnActionExecuting(actionContext);
        }

        public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (cancellationToken.CanBeCanceled && cancellationToken.IsCancellationRequested)
                return Task.FromResult<CorsPolicy>(null);

            return Task.FromResult(policy);
        }

        #endregion

        #region private

        private void SetValidOrigins(string appSettingKey)
        {
            // APP SETTING KEY: <add key="EnableCors.Origins" value="http://www.zippitydoodah.com" />
            var origins = string.Empty;
            if (!string.IsNullOrEmpty(appSettingKey))
            {
                origins = ConfigurationManager.AppSettings[appSettingKey];
                if (!string.IsNullOrEmpty(origins))
                {
                    foreach (string origin in origins.Split(",;|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
                        policy.Origins.Add(origin);
                }
            }
        }

        #endregion

        #endregion
    }
}
namespace My.Application.Web.Controllers
{
    using Security;
    using My.Application.Diagnostics;
    using My.Application.Framework.Configuration;
    using My.Application.Models;
    using My.Application.Process;
    using System;
    using System.Configuration;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Messaging;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    using System.Web.Http.Cors;
    using System.Xml.Linq;
    using System.Xml.Serialization;

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class OutboundEventController : ApiControllerBase
    {
        #region <Actions>

        [HttpGet]
        public HttpResponseMessage Ping()
        {
            TraceHandler.TraceIn(TraceLevel.Info);

            if (Request.Headers.Referrer == null)
                TraceHandler.TraceAppend(MESSAGE_REFERRER_NULL);

            if (Request.Headers.Referrer != null)
                TraceHandler.TraceAppend(string.Format(FORMAT_REFERRER, Request.Headers.Referrer));

            TraceHandler.TraceOut();
            return Request.CreateResponse(HttpStatusCode.OK, "Ping back at cha...");
        }

        [HttpPost]
        [EnableWebApiCorsFromAppSettings("EnableCors.Origins")]
        public HttpResponseMessage Enqueue(HttpRequestMessage request)
        {
            TraceHandler.TraceIn(TraceLevel.Info);

            if (Request.Headers.Referrer == null)
                TraceHandler.TraceAppend(MESSAGE_REFERRER_NULL);

            if (Request.Headers.Referrer != null)
                TraceHandler.TraceAppend(string.Format(FORMAT_REFERRER, Request.Headers.Referrer));

            try 
            {
                // Do Amazing Stuff Here...

                TraceHandler.TraceAppend(FORMAT_ENQUEUED_SUCCESS, claimId);
            }
            catch (Exception ex)
            {
                TraceHandler.TraceError(ex);
                TraceHandler.TraceOut();

                EnqueueToPoison(ex, claimMessage);
                return Request.CreateResponse(HttpStatusCode.InternalServerError, GetHttpError());
            }

            TraceHandler.TraceOut();

            // FORCE: Correct Header
            var response = Request.CreateResponse(HttpStatusCode.OK, string.Format(FORMAT_ENQUEUED_SUCCESS, claimId));
            response.Headers.Add("Access-Control-Allow-Origin", "*");
            return response;
        }

        #endregion

        private string GetClaimId(HttpRequestMessage request)
        {
            var stream = request.Content.ReadAsStreamAsync().Result;
            var xdoc = XDocument.Load(stream);
            var result = GetElementValue(xdoc, "ClaimId");

            return result;
        }

        private ClaimMessage CreateClaimMessage(string claimId, string process)
        {
            ClaimMessage message = new ClaimMessage();

            message.ClaimID = claimId;
            message.Process = process;

            return message;
        }

        private void Enqueue(ClaimMessage claimMessage)
        {
            var queueName = ConfigurationManager.AppSettings[Settings.Messaging.Queue.Name].ToString();
            var queue = new MessageQueue(queueName);
            queue.DefaultPropertiesToSend.Recoverable = true;

            TraceHandler.TraceAppend(FORMAT_QUEUE_NAME, queueName);

            MessageQueueTransaction transaction;
            transaction = new MessageQueueTransaction();
            transaction.Begin();

            var message = new System.Messaging.Message();
            message.Formatter = new XmlMessageFormatter(new Type[] { typeof(ClaimMessage) });

            message.Label = "ClaimID " + claimMessage.ClaimID;

            message.Body = claimMessage;
            queue.Send(message, transaction);

            transaction.Commit();
            queue.Close();
        }

        private void EnqueueToPoison(Exception exception, ClaimMessage claimdata)
        {
            TraceHandler.TraceIn(TraceLevel.Info);

            var poison = ToPoisonMessage(exception, claimdata);
            var message = new System.Messaging.Message();

            try
            {
                var poisonQueueName = ConfigurationManager.AppSettings[Settings.Messaging.PoisonQueue.Name].ToString();

                TraceHandler.TraceAppend(FORMAT_QUEUE_NAME, poisonQueueName);

                if (MessageQueue.Exists(poisonQueueName))
                {
                    var queue = new MessageQueue(poisonQueueName);
                    queue.DefaultPropertiesToSend.Recoverable = true;

                    var transaction = new MessageQueueTransaction();
                    transaction.Begin();

                    message.Formatter = new XmlMessageFormatter(new Type[] { typeof(PoisonClaimMessage) });
                    message.Label = "Poison ClaimID " + poison.ClaimID;

                    var xmlSerializer = new XmlSerializer(poison.GetType());
                    xmlSerializer.Serialize(message.BodyStream, poison);

                    queue.Send(message, transaction);

                    TraceHandler.TraceAppend(FORMAT_ENQUEUED_POISON_SUCCESS, poison.ClaimID);

                    transaction.Commit();
                    queue.Close();
                }
            }
            catch(Exception ex)
            {
                // An error occurred while enqueuing to POISON
                var poisonXml = ToString(poison);

                TraceHandler.TraceError(ex);
                TraceHandler.TraceAppend(poisonXml);
            }
            finally
            {
                TraceHandler.TraceOut();
            }
        }


        #endregion
    }
}
  <appSettings>
    <add key="EnableCors.Origins" value="" />
  </appSettings>
名称空间My.Application.Security
{
使用My.Application.Diagnostics;
使用制度;
使用系统配置;
使用系统诊断;
Net系统;
使用System.Net.Http;
使用系统线程;
使用System.Threading.Tasks;
使用System.Web.Cors;
使用System.Web.Http.Controller;
使用System.Web.Http.Cors;
使用System.Web.Http.Filters;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,AllowMultiple=false)]
公共类启用WebApicorsFromAppSettingsAttribute:ActionFilterAttribute,ICorsPolicyProvider
{
#区域
私有常量字符串异常\u CONTEXT\u NULL=“拒绝访问:HttpActionContext不能为NULL。”;
private const string异常\u referer\u NULL=“访问被拒绝:referer不能为NULL。”;
private const string FORMAT_INVALID_referer=“拒绝访问:“{0}”不是有效的referer。”;
已为此请求处理了private const string FORMAT_referer=“referer:{0}”;
私有常量字符串格式\u referer\u FOUND=“referer IsFound:{0}。”;
私人只读公司政策;
#端区
#区域
public EnableWebApiCorsFromAppSettingsAttribute(字符串appSettingKey,bool allowAnyHeader=true,bool allowAnyMethod=true,bool supportsCredentials=true)
{
策略=新公司策略();
policy.AllowAnyOrigin=false;
policy.AllowAnyHeader=AllowAnyHeader;
policy.AllowAnyMethod=AllowAnyMethod;
policy.SupportsCredentials=SupportsCredentials;
设置ValidOrigins(应用设置键);
if(policy.origines.Count==0)
policy.AllowAnyOrigin=true;
}
#端区
#区域
#地区公众
公共重写无效OnActionExecuting(HttpActionContext actionContext)
{
TraceHandler.TraceIn(TraceLevel.Info);
if(actionContext==null)
抛出新ArgumentNullException(“HttpActionContext”);
if(actionContext.Request.Headers.referer==null)
actionContext.Response=actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidded,EXCEPTION\u Referer\u NULL);
var referer=actionContext.Request.Headers.referer.ToString();
TraceHandler.TraceAppend(string.Format(formatreferer,referer));
//如果未设置原点,则不执行任何操作
如果(policy.origines.Count>0)
{
var isFound=policy.Origins.Contains(referer);
TraceHandler.TraceAppend(string.Format(Format\u referer\u FOUND,isFound));
如果(!isFound)
{
TraceHandler.TraceAppend(“IsFound为FALSE”);