Enable OPTIONS header for CORS on .NET Core Web API

后端 未结 7 1536
温柔的废话
温柔的废话 2020-11-28 06:55

I solved this problem after not finding the solution on Stackoverflow, so I am sharing my problem here and the solution in an answer.

After enabling a cross domain p

相关标签:
7条回答
  • 2020-11-28 07:28

    I wanted to allow this for a single method, not using a middleware to allow this on any method. This is what I ended doing:

    Manual handling of the 'OPTIONS' method

    [HttpOptions("/find")]
    public IActionResult FindOptions()
    {
        Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
        Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
        Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
        Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
        return NoContent();
    }
    

    [HttpPost("/find")]
    public async Task<IActionResult> FindOptions([FromForm]Find_POSTModel model)
    {
        AllowCrossOrigin();
        
        // your code...
    }
    
    private void AllowCrossOrigin()
    {
        Uri origin = null;
        Uri.TryCreate(Request.Headers["Origin"].FirstOrDefault(), UriKind.Absolute, out origin);
    
        if (origin != null && IsOriginAllowed(origin))
            Response.Headers.Add("Access-Control-Allow-Origin", $"{origin.Scheme}://{origin.Host}");
    }
    

    And of course, you can implement IsOriginAllowed as you wish

    private bool IsOriginAllowed(Uri origin)
    {
        const string myDomain = "mydomain.com";
        const string[] allowedDomains = new []{ "example.com", "sub.example.com" };
    
        return 
               allowedDomains.Contains(origin.Host) 
               || origin.Host.EndsWith($".{myDomain}");
    }
    
    

    You can find more details on how to enable CORS for POST requests on a single endpoint

    0 讨论(0)
  • 2020-11-28 07:33

    welcome .

    [HttpOptions("/find")] public IActionResult FindOptions()

    {
        Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
        Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
        Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
        Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
        return NoContent();
    }`enter code here`
    
    0 讨论(0)
  • 2020-11-28 07:39

    This worked for me:

    Make sure that this:

    app.UseCors(builder => {
        builder.AllowAnyOrigin();
        builder.AllowAnyMethod();
        builder.AllowAnyHeader();
    });
    

    Occurs before any of these:

    app.UseHttpsRedirection();
    app.UseDefaultFiles();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    

    Remember, we are dealing with a "pipeline". The cors stuff has to be first.

    -gimzani

    0 讨论(0)
  • 2020-11-28 07:40

    There is no need in an additional middleware. As already mentioned above the only thing needed is the OPTIONS method allowed in Cors configuration. You may AllowAnyMethod as suggested here: https://stackoverflow.com/a/55764660/11921910

    But it's safer to just allow the specific stuff like this:

    app.UseCors(builder => builder
    .WithOrigins("https://localhost", "https://production.company.com") /* list of environments that will access this api */
    .WithMethods("GET", "OPTIONS") /* assuming your endpoint only supports GET */
    .WithHeaders("Origin", "Authorization") /* headers apart of safe-list ones that you use */
    );
    

    Some headers are always allowed: https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header

    0 讨论(0)
  • 2020-11-28 07:44

    Add a middleware class to your project to handle the OPTIONS verb.

    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Hosting;
    
    namespace Web.Middlewares
    {
        public class OptionsMiddleware
        {
            private readonly RequestDelegate _next;
    
            public OptionsMiddleware(RequestDelegate next)
            {
                _next = next;
            }
    
            public Task Invoke(HttpContext context)
            {
                return BeginInvoke(context);
            }
    
            private Task BeginInvoke(HttpContext context)
            {
                if (context.Request.Method == "OPTIONS")
                {
                    context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
                    context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
                    context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
                    context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
                    context.Response.StatusCode = 200;
                    return context.Response.WriteAsync("OK");
                }
    
                return _next.Invoke(context);
            }
        }
    
        public static class OptionsMiddlewareExtensions
        {
            public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
            {
                return builder.UseMiddleware<OptionsMiddleware>();
            }
        }
    }
    

    Then add app.UseOptions(); this as the first line in Startup.cs in the Configure method.

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseOptions();
    }
    
    0 讨论(0)
  • 2020-11-28 07:45

    I know it has been answered. Just answering with the updated information. So it would help others.

    It is now built into the ASP.NET Core framework.

    Just follow https://docs.microsoft.com/en-us/aspnet/core/security/cors

    and replace

        app.UseCors(builder =>
       builder.WithOrigins("http://example.com"));
    

    with

            app.UseCors(builder =>
           builder.WithOrigins("http://example.com")
                  .AllowAnyHeader()
                  .AllowAnyMethod()
                  .AllowCredentials());
    
    0 讨论(0)
提交回复
热议问题