วิธีเปิดใช้งาน CORS ใน ASP.net Core WebAPI


189

สิ่งที่ฉันพยายามทำ

ฉันมี ASP.Net Core Web API แบ็กเอนด์ที่โฮสต์บน Azure Free Plan (ซอร์สโค้ด: https://github.com/killerrin/Portfolio-Backend )

ฉันมีเว็บไซต์ลูกค้าที่ฉันต้องการใช้ API นั้น แอปพลิเคชันไคลเอนต์จะไม่ถูกโฮสต์บน Azure แต่จะถูกโฮสต์บน Github Pages หรือบริการเว็บโฮสติ้งอื่นที่ฉันสามารถเข้าถึงได้ ด้วยเหตุนี้ชื่อโดเมนจะไม่ตรง

เมื่อมองถึงสิ่งนี้ฉันต้องเปิดใช้งาน CORS ทางฝั่ง Web API แต่ฉันได้ลองทุกอย่างเป็นเวลาหลายชั่วโมงแล้วและปฏิเสธที่จะทำงาน

ฉันมีการตั้งค่าไคลเอนต์ มันเป็นเพียงลูกค้าที่เรียบง่ายเขียนใน React.js ฉันกำลังเรียก API ผ่าน AJAX ใน Jquery ไซต์ React ใช้งานได้ดังนั้นฉันจึงไม่ทราบ การเรียก API ของ Jquery ทำงานได้ตามที่ฉันยืนยันในความพยายามที่ 1 นี่คือวิธีการโทร

    var apiUrl = "http://andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication";
    //alert(username + "|" + password + "|" + apiUrl);
    $.ajax({
        url: apiUrl,
        type: "POST",
        data: {
            username: username,
            password: password
        },
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            var authenticatedUser = JSON.parse(response);
            //alert("Data Loaded: " + authenticatedUser);
            if (onComplete != null) {
                onComplete(authenticatedUser);
            }
        },
        error: function (xhr, status, error) {
            //alert(xhr.responseText);
            if (onComplete != null) {
                onComplete(xhr.responseText);
            }
        }
    });

สิ่งที่ฉันได้ลอง


ความพยายามที่ 1 - วิธีที่ 'เหมาะสม'

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

ฉันได้ทำตามบทช่วยสอนนี้บนเว็บไซต์ Microsoft เป็น T แล้วลองทั้ง 3 ตัวเลือกในการเปิดใช้งานได้ทั่วโลกใน Startup.cs การตั้งค่าบนตัวควบคุมทุกตัวและลองใช้กับทุกการกระทำ

ทำตามวิธีนี้ Cross Domain ใช้งานได้ แต่ทำงานบน Action เดียวบนคอนโทรลเลอร์เดี่ยว (POST to AccountController) เท่านั้น สำหรับทุกอย่างอื่นMicrosoft.AspNetCore.Corsมิดเดิลแวร์ปฏิเสธที่จะตั้งค่าส่วนหัว

ฉันติดตั้งMicrosoft.AspNetCore.Corsผ่าน NUGET และเป็นเวอร์ชั่น1.1.2

นี่คือวิธีที่ฉันมีการตั้งค่าใน Startup.cs

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add Cors
        services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
        {
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader();
        }));

        // Add framework services.
        services.AddMvc();
        services.Configure<MvcOptions>(options =>
        {
            options.Filters.Add(new CorsAuthorizationFilterFactory("MyPolicy"));
        });

        ...
        ...
        ...
    }

    // This method gets called by the runtime. Use this method to configure 
    //the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        // Enable Cors
        app.UseCors("MyPolicy");

        //app.UseMvcWithDefaultRoute();
        app.UseMvc();

        ...
        ...
        ...
    }

อย่างที่คุณเห็นฉันกำลังทำทุกอย่างตามที่บอก ฉันเพิ่ม Cors ก่อน MVC ทั้งสองครั้งและเมื่อไม่ได้ผลฉันพยายามใส่[EnableCors("MyPolicy")]คอนโทรลเลอร์ทุกตัวเป็นอย่างนั้น

[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller

พยายาม 2 - เดียรัจฉานบังคับมัน

https://andrewlock.net/adding-default-security-headers-in-asp-net-core/

หลังจากพยายามหลายชั่วโมงก่อนหน้านี้ฉันคิดว่าฉันจะพยายามทำให้เป็นจริงโดยพยายามตั้งค่าส่วนหัวด้วยตนเองบังคับให้พวกเขาทำงานทุกครั้ง ฉันทำสิ่งนี้ตามบทช่วยสอนนี้เกี่ยวกับการเพิ่มส่วนหัวในทุก ๆ การตอบกลับด้วยตนเอง

นี่คือส่วนหัวที่ฉันเพิ่ม

.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")

นี่คือส่วนหัวอื่น ๆ ที่ฉันลองซึ่งล้มเหลว

.AddCustomHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "content-type, accept, X-PINGOTHER")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Host, User-Agent, Accept, Accept: application/json, application/json, Accept-Language, Accept-Encoding, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Connection, Content-Type, Content-Type: application/json, Authorization, Connection, Origin, Referer")

ด้วยวิธีนี้ส่วนหัว Cross Site นั้นได้ถูกนำไปใช้อย่างเหมาะสมและพวกมันจะปรากฏในคอนโซลนักพัฒนาซอฟต์แวร์ของฉันและในบุรุษไปรษณีย์ อย่างไรก็ตามปัญหาคือในขณะที่มันผ่านการAccess-Control-Allow-Originตรวจสอบเว็บเบราว์เซอร์โยนแบบ hissy พอดี (ฉันเชื่อ) Access-Control-Allow-Headersระบุ415 (Unsupported Media Type)

ดังนั้นวิธีเดรัจฉานบังคับไม่ทำงานเช่นกัน


ในที่สุด

มีใครได้รับสิ่งนี้ในการทำงานและสามารถยืมมือหรือเพียงแค่สามารถชี้ให้ฉันไปในทิศทางที่ถูกต้อง?


แก้ไข

ดังนั้นเพื่อให้การเรียก API ผ่านไปได้ฉันต้องหยุดใช้ JQuery และเปลี่ยนเป็นXMLHttpRequestรูปแบบPure Javascript

พยายาม 1

ฉันจัดการที่จะได้รับMicrosoft.AspNetCore.Corsในการทำงานโดยทำตามคำตอบ MindingData ยกเว้นในConfigureวิธีการวางก่อนapp.UseCorsapp.UseMvc

นอกจากนี้เมื่อผสมกับ Javascript API Solution options.AllowAnyOrigin()เพื่อรองรับสัญลักษณ์ตัวแทนก็เริ่มทำงานได้เช่นกัน

พยายาม 2

ดังนั้นฉันจึงพยายามรับ 2 (เดรัจฉานบังคับ) เพื่อให้ทำงาน ... โดยมีข้อยกเว้นเพียงอย่างเดียวที่ไวด์การ์ดสำหรับAccess-Control-Allow-Originใช้งานไม่ได้และดังนั้นฉันจึงต้องตั้งค่าโดเมนที่สามารถเข้าถึงได้ด้วยตนเอง

เห็นได้ชัดว่ามันไม่เหมาะเพราะฉันแค่ต้องการให้ WebAPI นี้เปิดกว้างสำหรับทุกคน แต่อย่างน้อยก็เหมาะสำหรับฉันในเว็บไซต์อื่นซึ่งหมายความว่าเป็นการเริ่มต้น

app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
    .AddDefaultSecurePolicy()
    .AddCustomHeader("Access-Control-Allow-Origin", "http://localhost:3000")
    .AddCustomHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE")
    .AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Content-Type, Authorization"));

2
สำหรับคุณ415 (Unsupported Media Type)ปัญหากำหนดหัวข้อการร้องขอไปContent-Type application/json
Technetium

5
ขอบคุณที่ใช้เวลาเขียนคำถามเชิงพรรณนา
user1007074

1
หากคุณกำลังทดสอบโดยใช้บุรุษไปรษณีย์ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่า Origin เป็น * หรือบางอย่างสำหรับส่วนหัวคำขอจากนั้นความพยายาม # 1 ควรใช้งานได้ หากไม่มีส่วนหัวนี้ Access-Control-Allow-Origin จะไม่ถูกส่งคืนในส่วนหัวการตอบกลับ
tala9999

คำตอบ:


238

เนื่องจากคุณมีนโยบาย CORS ที่ง่ายมาก (อนุญาตคำขอทั้งหมดจากโดเมน XXX) คุณจึงไม่จำเป็นต้องทำให้ซับซ้อน ลองทำสิ่งต่อไปนี้ก่อน (การใช้งาน CORS ขั้นพื้นฐานมาก)

หากคุณยังไม่ได้ติดตั้งแพ็คเกจ nuget ของ CORS

Install-Package Microsoft.AspNetCore.Cors

ในวิธีการ ConfigureServices ของ startup.cs ของคุณเพิ่มบริการ CORS

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(); // Make sure you call this previous to AddMvc
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

จากนั้นในวิธีการกำหนดค่าของ startup.cs ของคุณเพิ่มต่อไปนี้:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // Make sure you call this before calling app.UseMvc()
    app.UseCors(
        options => options.WithOrigins("http://example.com").AllowAnyMethod()
    );

    app.UseMvc();
}

ตอนนี้ให้มันไป นโยบายใช้เมื่อคุณต้องการนโยบายที่แตกต่างกันสำหรับการกระทำที่แตกต่างกัน (เช่นโฮสต์ที่แตกต่างกันหรือส่วนหัวที่แตกต่างกัน) สำหรับตัวอย่างง่ายๆของคุณคุณไม่ต้องการมัน เริ่มด้วยตัวอย่างง่ายๆและปรับแต่งตามที่คุณต้องการ

อ่านเพิ่มเติม: http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/


3
XMLHttpRequest ไม่สามารถโหลดandrewgodfroyportfolioapi.azurewebsites.net/api/Authentication การตอบสนองต่อคำขอ preflight ไม่ผ่านการตรวจสอบการควบคุมการเข้าถึง: ไม่มีส่วนหัว 'Access-Control-Allow-Origin' บนทรัพยากรที่ร้องขอ Origin ' localhost: 3000 ' ไม่อนุญาตให้เข้าถึง การตอบกลับมีรหัสสถานะ HTTP 415
killerrin

7
สิ่งนี้ไม่น่าจะเป็นไปได้เมื่อคุณลงทะเบียนapp.UseCors หลังจากแอพ `` app.UseMvc () ' Middlewares จะดำเนินการตามลำดับที่ลงทะเบียน
Tseng

24
ใช้ app.UseCors ก่อน app.UseMvc ในวิธีการกำหนดค่าดูเหมือนว่าจะทำงาน ด้วยเหตุผลบางอย่างลำดับไม่สำคัญ
MrClan

1
สำหรับฉันปัญหาที่ใหญ่ที่สุดของ CORS ใน 2.0 ก็คือมันไม่ได้บอกว่าผิดอะไรเพียง แต่ล้มเหลวในการตั้งค่าส่วนหัว CORS หมายเหตุ : อย่าลืมเพิ่มส่วนหัวที่คุณต้องการทั้งหมดในนโยบายไม่เช่นนั้นจะล้มเหลว (ฉันมีประเภทเนื้อหา) นอกจากนี้ยังมีสิ่งที่แปลกสำหรับฉันที่ล ธ มิดเดิ้ลไม่ได้ประมวลผลคำขอเบรกเพียงแจ้งในบันทึกว่าต้นกำเนิดไม่ได้รับอนุญาตและผ่าน .. ขอเพิ่มเติม (สั่งมิดเดิลแวร์ถูกต้อง)
Andrii M4n0w4R

2
ฉันต้องเปิดใช้งานoptions.DisableHttpsRequirement();เพื่อให้สิ่งนี้ทำงานได้ ดูเหมือนว่าการตั้งค่า https cors ไม่ได้ใช้
Michael Brown

208
  • ในConfigureServicesเพิ่ม services.AddCors(); บริการ BEFORE.AddMvc ();

  • เพิ่ม UseCors ในกำหนดค่า

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

จุดหลักคือเพิ่มว่าก่อนที่จะapp.UseCorsapp.UseMvc()

ตรวจสอบให้แน่ใจว่าคุณประกาศฟังก์ชัน CORS ก่อน MVC ดังนั้นมิดเดิลแวร์จะเริ่มทำงานก่อนที่ MVC ไปป์ไลน์จะได้รับการควบคุมและยกเลิกคำร้องขอ

หลังจากวิธีการด้านบนทำงานได้คุณสามารถเปลี่ยนการกำหนดค่า ORIGIN เฉพาะเพื่อรับสาย API และหลีกเลี่ยงการปล่อย API ของคุณเพื่อเปิดให้ทุกคน

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
    {
        builder.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader();
    }));

    services.AddMvc();
}

ในวิธีการกำหนดค่าบอก CORS ให้ใช้นโยบายที่คุณเพิ่งสร้างขึ้น:

app.UseCors("ApiCorsPolicy");
app.UseMvc();

ฉันเพิ่งพบบทความกระชับในเรื่อง - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi


1
มันใช้งานได้สำหรับฉัน codeproject.com/Articles/1150023/…
hubert17

17
นี่ควรจะได้ upvotes มากขึ้นเป็นจุดเริ่มต้นที่ดี จากประสบการณ์ของฉันในการเขียนโค้ดมากว่า 25 ปีมันเป็นเรื่องดีที่ได้รู้ว่าจะเปิดประตูระบายน้ำเพื่อให้แน่ใจได้ว่ามันเป็น "งาน" จริง ๆ แล้วจึงปิด / รักษาสิ่งต่าง ๆ ตามที่จำเป็น
Indy-Jones

4
เพียงพูดถึงสิ่งนี้ตรงกันข้ามกับConfigure()คำสั่งซื้อนั้นไม่สำคัญจริงๆภายในConfigureServices()
B12 Toaster

ฉันใช้ลิงก์ในเครื่องอ่านเพิ่มเติมและขั้นตอนเหล่านั้นสามารถแก้ไขข้อผิดพลาดนี้ได้ ฉันไม่แน่ใจว่าควรวางการเปลี่ยนแปลงเหล่านี้ไว้ที่ใด (ฉันคิดว่า API) ลิงก์ยืนยันว่าควรวางไว้ใน API ขอบคุณสำหรับความช่วยเหลือ ฉันปั่นล้อทั้งหมดโดยมีข้อผิดพลาดนี้
Richard

1
FYI - ข้อมูลจำเพาะ CORS ยังระบุว่าการตั้งค่าต้นกำเนิดเป็น "*" (ต้นกำเนิดทั้งหมด) ไม่ถูกต้องหากส่วนหัวของ Access-Control-Allow-Credentials แสดงอยู่ ความหมายที่คุณไม่สามารถใช้AllowCredentials()กับAllowAnyOrigin()เช่นเดียวกับข้างต้น หากต้องการใช้คุณจะต้องตั้ง AllowCredentials() docs.microsoft.com/en-us/aspnet/core/security/…WithOrigins()
Nick De Beer

28

ฉันสร้างคลาสมิดเดิลแวร์ของตัวเองที่ทำงานให้ฉันฉันคิดว่ามีบางอย่างผิดปกติกับคลาสมิดเดิลแวร์. net core

public class CorsMiddleware
{
    private readonly RequestDelegate _next;

    public CorsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext httpContext)
    {
        httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
        httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
        httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
        return _next(httpContext);
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class CorsMiddlewareExtensions
{
    public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<CorsMiddleware>();
    }
}

และใช้วิธีนี้ใน startup.cs

app.UseCorsMiddleware();

วิธีการใช้งานที่หรูหรามากของ Access-Control-Allow-Origin
Artur Poniedziałek

สิ่งนี้ใช้ได้กับ WebAPI และ MVC และไม่มีการอ้างอิงขอบคุณ!
Joe

ฉันยังสงสัยเกี่ยวกับเรื่องนี้ด้วย แต่มันก็ใช้ได้กับฉัน ฉันพยายามโดยทั่วไปทุกวิธีอื่นเพื่อให้บรรลุสิ่งนี้ที่ฉันพบบนอินเทอร์เน็ต แต่ไม่ว่าเซิร์ฟเวอร์จะไม่ตอบสนองกับส่วนหัวการเข้าถึง มันใช้งานได้ดีมาก ฉันกำลังเรียกใช้ aspnetcore 2.1
Jordan

คุณควรส่งคืนส่วนหัว cors ต่อเมื่อไคลเอนต์ส่งส่วนหัว "Origin" ตามคำขอ ใน CospMiddleware ดั้งเดิมมันมีลักษณะเช่นนี้:if (!context.Request.Headers.ContainsKey(CorsConstants.Origin)) return this._next(context);
Andrew Prigorshnev

1
อาจเป็น "สิ่งผิดปกติกับคลาสมิดเดิลแวร์. net core" เพราะคุณไม่ได้เพิ่มส่วนหัว "Origin" เมื่อทำการทดสอบด้วย curl หรืออะไรทำนองนี้ เบราว์เซอร์เพิ่มส่วนหัวนี้โดยอัตโนมัติเมื่อคุณทำการร้องขอในรหัส js
Andrew Prigorshnev

18

ในกรณีของฉันgetขอเพียงทำงานได้ดีตามคำตอบของ MindingData สำหรับคำขอประเภทอื่นคุณต้องเขียน:

app.UseCors(corsPolicyBuilder =>
   corsPolicyBuilder.WithOrigins("http://localhost:3000")
  .AllowAnyMethod()
  .AllowAnyHeader()
);

อย่าลืมเพิ่ม .AllowAnyHeader()


เห็นด้วยกับ Towhid ที่ต้องการ AllowAnyHeader () มันทำให้เซิร์ฟเวอร์ได้รับคำขอ OPTIONS ถ้าคำขอของ HEADER หายไปบางอย่าง
Rivon

.AllowAnyHeader () ทำเพื่อฉันฉันมีปัญหากับการตอบกลับ preflight
takaz

11

เพื่อขยายuser8266077 's คำตอบที่ผมพบว่าผมยังจำเป็นในการตอบสนองอุปทานตัวเลือกสำหรับการร้องขอ preflightใน .NET หลัก 2.1 แสดงตัวอย่างสำหรับกรณีการใช้งานของฉัน:

// https://stackoverflow.com/a/45844400
public class CorsMiddleware
{
  private readonly RequestDelegate _next;

  public CorsMiddleware(RequestDelegate next)
  {
    _next = next;
  }

  public async Task Invoke(HttpContext context)
  {
    context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
    context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    // Added "Accept-Encoding" to this list
    context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
    context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
    // New Code Starts here
    if (context.Request.Method == "OPTIONS")
    {
      context.Response.StatusCode = (int)HttpStatusCode.OK;
      await context.Response.WriteAsync(string.Empty);
    }
    // New Code Ends here

    await _next(context);
  }
}

จากนั้นเปิดใช้งานมิดเดิลแวร์อย่างใน Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UseMiddleware(typeof(CorsMiddleware));
  // ... other middleware inclusion such as ErrorHandling, Caching, etc
  app.UseMvc();
}

1
ฉันแนะนำให้เพิ่มมิดเดิลแวร์แบบนั้น:app.Use<CorsMiddleware>();
Albert221

คุณสามารถแทนที่ 2 ligne: context.Response.StatusCode = (int) HttpStatusCode.OK; รอบริบทการตอบสนอง.WriteAsync (string.Empty); ด้วยง่าย ๆ : กลับมา;
Hayha

1
หากต้องการขยายคำตอบของ @ user8266077 ให้ขยาย: ระวังว่าหากการร้องขอด้วยเหตุผลอื่นล้มเหลวมิดเดิลแวร์นี้จะส่งข้อยกเว้นและส่วนหัวจะไม่ถูกตั้งค่า หมายความว่าในส่วนหน้ามันจะยังคงดูเหมือน CORS แม้ว่ามันจะเป็นอะไรที่ต่างออกไปโดยสิ้นเชิง ฉันข้ามสิ่งนี้โดยจับข้อยกเว้นใด ๆawait _next(context)และตั้งค่ารหัสสถานะและการตอบสนองด้วยตนเองหากเกิดเหตุการณ์นี้ ฉันยังต้องเพิ่ม "การอนุญาต" ใน Access-Control-Allow-Headers เพื่อให้คำขอ preflight ทำงานเมื่อทำการร้องขอจากการตอบสนองที่ต้องได้รับอนุญาต
อดัม

11
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {      
       app.UseCors(builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials()
            );
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
    }

.SetIsOriginAllowed ((โฮสต์) => true) แก้ไขให้ฉัน
JensB

ว้าวฉันเลยคาดหวังว่าจะได้คำตอบอื่นใดในการทำงานมาก่อนเจ้าตัวน้อยนี้ที่มีเพียง 3 โหวต แต่ฉันลองแต่ละคนอย่างพิถีพิถัน ... ในสิ่งที่ฉันไปเพื่อคุณและมันก็ใช้ได้ ขอบคุณ
roberto tomás

นี่คือสิ่งที่ทำงานกับฉันใน. NET Core 3.1 เพื่อให้อะไรมาก
JustinHui

10

ฉันดิ้นรนกับสิ่งนี้เป็นเวลา DAYS

ในที่สุดผมก็มีมันในการทำงานโดยการย้ายapp.UseCors(CORS_POLICY);ไปท็อปConfigure()ของ

https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas

ตรวจสอบให้แน่ใจว่าคุณประกาศฟังก์ชัน CORS ก่อน> MVC เนื่องจากต้องใช้ส่วนหัวก่อนที่ MVC จะดำเนินการตามคำขอให้เสร็จสมบูรณ์

<= แม้ว่าแอพของฉันไม่ได้โทรUseMVC()แต่การย้ายUseCors()ไปที่ด้านบนจะแก้ไขปัญหาได้

นอกจากนี้:

  • Microsoft.AspNetCore.Corsเคยเป็นแพคเกจ NuGet ที่จำเป็นใน. Net Core 2 และต่ำกว่า; ตอนนี้เป็นส่วนหนึ่งของ Microsoft.AspNetCore โดยอัตโนมัติใน. Net Core 3 และสูงกว่า
  • builder.AllowAnyOrigin()และ.AllowCredentials()ตัวเลือก CORS เป็นเอกสิทธิ์เฉพาะบุคคลใน. Net Core 3 และสูงกว่า
  • ดูเหมือนว่านโยบาย ธ httpsที่จะต้องโทรเชิงมุมเซิร์ฟเวอร์ด้วย http URL ดูเหมือนจะให้ข้อผิดพลาด CORS โดยไม่คำนึงถึงการกำหนดค่า CORS ของเซิร์ฟเวอร์. Core Core ตัวอย่างเช่นhttp://localhost:52774/api/Contactsจะให้ข้อผิดพลาด CORS; เพียงแค่เปลี่ยน URL ให้ใช้https://localhost:44333/api/Contactsงานได้

หมายเหตุเพิ่มเติม :

ในกรณีของฉันล ธ จะไม่ทำงานจนกว่าฉันจะย้ายข้างต้นapp.UseCors()app.UseEndpoints(endpoints => endpoints.MapControllers())


2
อันนี้ควรเป็นคำตอบถ้าคุณใช้ Net Core 3 ขอบคุณที่ช่วยชีวิตฉันไว้!
Canada Wan

2
"ด้วยการกำหนดเส้นทางจุดสิ้นสุดมิดเดิลแวร์ CORS ต้องถูกกำหนดค่าให้ดำเนินการระหว่างการเรียกไปยัง UseRouting และ UseEndpoints การกำหนดค่าที่ไม่ถูกต้องจะทำให้มิดเดิลแวร์หยุดทำงานอย่างถูกต้อง" ที่นี่docs.microsoft.com/en-us/aspnet/core/security/…
Mark Schultheiss

"ด้วยการกำหนดเส้นทางจุดสิ้นสุดมิดเดิลแวร์ CORS ต้องถูกกำหนดค่าให้ดำเนินการระหว่างการเรียกไปยัง UseRouting และ UseEndpoints การกำหนดค่าที่ไม่ถูกต้องจะทำให้มิดเดิลแวร์หยุดทำงานอย่างถูกต้อง" ที่นี่docs.microsoft.com/en-us/aspnet/core/security/…
Mark Schultheiss

7

ไม่มีขั้นตอนข้างต้นช่วยฉันอ่านบทความที่แก้ไขปัญหาได้แล้ว

ด้านล่างเป็นรหัส

public void ConfigureServices(IServiceCollection services)
{
    // Add service and create Policy with options
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials() );
    });


    services.AddMvc(); 
}

และ

public void Configure(IApplicationBuilder app)
{
    // ...

    // global policy - assign here or on each controller
    app.UseCors("CorsPolicy");

และด้านบนของแอ็คชั่นของฉัน

[EnableCors("CorsPolicy")]

2
นี่อาจเป็นความคิดที่ไม่ดี: คุณไม่ควรผสมมิดเดิลแวร์ ( app.UseCors()) กับ[EnableCors()]แอปพลิเคชันเดียวกัน คุณควรใช้อย่างใดอย่างหนึ่ง - แต่ไม่ใช่ทั้งสอง: docs.microsoft.com/en-us/aspnet/core/security/ … :Use the [EnableCors] attribute or middleware, not both in the same app.
FoggyDay

4

ลองเพิ่มjQuery.support.cors = true;ก่อนโทร Ajax

อาจเป็นไปได้ว่าข้อมูลที่คุณส่งไปยัง API นั้นไม่มีประสิทธิภาพ

ลองเพิ่มฟังก์ชัน JSON ต่อไปนี้

        var JSON = JSON || {};

    // implement JSON.stringify serialization
    JSON.stringify = JSON.stringify || function (obj) {

        var t = typeof (obj);
        if (t != "object" || obj === null) {

            // simple data type
            if (t == "string") obj = '"' + obj + '"';
            return String(obj);

        }
        else {

            // recurse array or object
            var n, v, json = [], arr = (obj && obj.constructor == Array);

            for (n in obj) {
                v = obj[n]; t = typeof (v);

                if (t == "string") v = '"' + v + '"';
                else if (t == "object" && v !== null) v = JSON.stringify(v);

                json.push((arr ? "" : '"' + n + '":') + String(v));
            }

            return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
        }
    };

    // implement JSON.parse de-serialization
    JSON.parse = JSON.parse || function (str) {
        if (str === "") str = '""';
        eval("var p=" + str + ";");
        return p;
    };

จากนั้นในข้อมูลของคุณ: วัตถุเปลี่ยนเป็น

    data: JSON.stringify({
        username: username,
        password: password
    }),

ขอบคุณสำหรับความช่วยเหลือของคุณ. ใช้ส่วนของคำตอบเพื่อหาคำตอบในท้ายที่สุดหลังจากรวมคำตอบของทุกคนเข้าด้วยกัน
killerrin

4

โซลูชันที่ง่ายที่สุดคือการเพิ่ม

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(options => options.AllowAnyOrigin());

        app.UseHttpsRedirection();
        app.UseMvc();
    }

ถึง Startup.cs


3

ฉันคิดว่าถ้าคุณใช้มิดเดิลแวร์CORSของคุณเองคุณต้องตรวจสอบให้แน่ใจว่ามันเป็นคำขอCORSจริงๆโดยการตรวจสอบส่วนหัวกำเนิด

 public class CorsMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMemoryCache _cache;
    private readonly ILogger<CorsMiddleware> _logger;

    public CorsMiddleware(RequestDelegate next, IMemoryCache cache, ILogger<CorsMiddleware> logger)
    {
        _next = next;
        _cache = cache;
        _logger = logger;
    }
    public async Task InvokeAsync(HttpContext context, IAdministrationApi adminApi)
    {
        if (context.Request.Headers.ContainsKey(CorsConstants.Origin) || context.Request.Headers.ContainsKey("origin"))
        {
            if (!context.Request.Headers.TryGetValue(CorsConstants.Origin, out var origin))
            {
                context.Request.Headers.TryGetValue("origin", out origin);
            }

            bool isAllowed;
            // Getting origin from DB to check with one from request and save it in cache 
            var result = _cache.GetOrCreateAsync(origin, async cacheEntry => await adminApi.DoesExistAsync(origin));
            isAllowed = result.Result.Result;

            if (isAllowed)
            {
                context.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
                context.Response.Headers.Add(
                    CorsConstants.AccessControlAllowHeaders,
                    $"{HeaderNames.Authorization}, {HeaderNames.ContentType}, {HeaderNames.AcceptLanguage}, {HeaderNames.Accept}");
                context.Response.Headers.Add(CorsConstants.AccessControlAllowMethods, "POST, GET, PUT, PATCH, DELETE, OPTIONS");

                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("CORS with origin {Origin} was handled successfully", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                await _next(context);
            }
            else
            {
                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("Preflight CORS request with origin {Origin} was declined", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                _logger.LogInformation("Simple CORS request with origin {Origin} was declined", origin);
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                return;
            }
        }

        await _next(context);
    }

ขอบคุณมาก. ฉันเกือบจะไปถั่วถามตัวเองว่าทำไมAccess-Control-Allow-Originส่วนหัวไม่ได้ออกโดยเซิร์ฟเวอร์ ที่จริงฉันส่งคำขอผ่านบุรุษไปรษณีย์โดยไม่มีOriginส่วนหัว สิ่งนี้ช่วยชีวิตฉันไว้! (หรืออย่างน้อย forenoon ของฉัน;))
Paul Kertscher

2

จากความคิดเห็นของคุณในคำตอบของ MindingData ไม่มีอะไรเกี่ยวข้องกับ CORS ของคุณทำงานได้ดี

การกระทำของผู้ควบคุมของคุณกำลังส่งคืนข้อมูลที่ผิด HttpCode 415 หมายถึง "ประเภทสื่อที่ไม่รองรับ" สิ่งนี้จะเกิดขึ้นเมื่อคุณส่งรูปแบบที่ไม่ถูกต้องไปยังคอนโทรลเลอร์ (เช่น XML ไปยังคอนโทรลเลอร์ที่ยอมรับ json เท่านั้น) หรือเมื่อคุณส่งคืนประเภทที่ไม่ถูกต้อง (return Xml ในคอนโทรลเลอร์

สำหรับการตรวจสอบหนึ่งครั้งภายหลังมี[Produces("...")]แอตทริบิวต์ในการกระทำของคุณ


ขอบคุณสำหรับความช่วยเหลือของคุณ. พยายามแก้ปัญหาใหม่และเล่นกับ JSON ถูกส่งออกและการทำงานหลังจากที่ฉัน stringified มันและได้ไปทำงาน
killerrin

2

สำหรับฉันมันไม่มีอะไรเกี่ยวข้องกับรหัสที่ฉันใช้ สำหรับ Azure เราต้องเข้าไปที่การตั้งค่าของ App Service บนเมนูด้านข้างรายการ "CORS" ที่นั่นฉันต้องเพิ่มโดเมนที่ฉันขอสิ่งจาก เมื่อฉันได้สิ่งนั้นทุกอย่างเป็นเวทมนตร์


2

ใน launchSettings.json ภายใต้ iisSettings ให้ตั้งค่า anonymousAuthentication เป็น true:

"iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:4200/",
      "sslPort": 0
    }
  }

จากนั้นใน Startup.cs ภายใต้ ConfigureServices ก่อน services.AddMvc ให้เพิ่ม:

services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
    builder
        .AllowAnyOrigin()
        .WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type")
        .AllowAnyMethod()
        .AllowCredentials();
}));

จากนั้นในการกำหนดค่าวิธีก่อน app.UseMvc () เพิ่ม:

app.UseCors("ApiCorsPolicy");

สิ่งนี้ทำเพื่อฉันฉันตั้งค่าโครงการของฉันสำหรับ Windows Authentication แต่แล้วต้องเปลี่ยนเป็นแบบไม่ระบุชื่อฉันมี CORS กำหนดค่าอย่างถูกต้อง แต่การตั้งค่านี้ใน launchSettings.json เป็นผู้ร้ายขอบคุณสำหรับการโพสต์นี้!
HaRoLD

2

ฉันใช้. Net CORE 3.1 และฉันใช้เวลานานหลายปีในการต่อสู้กับกำแพงกับสิ่งนี้เมื่อฉันรู้ว่ารหัสของฉันเริ่มทำงานได้จริง แต่สภาพแวดล้อมการแก้ไขข้อบกพร่องของฉันเสียดังนั้นนี่คือคำแนะนำ 2 ข้อหากคุณพยายามแก้ไขปัญหา ปัญหา:

  1. หากคุณกำลังพยายามบันทึกส่วนหัวการตอบสนองโดยใช้ ASP.NET มิดเดิลแวร์ส่วนหัว "Access-Control-Allow-Origin-Origin" จะไม่ปรากฏขึ้นแม้ว่าจะมีอยู่ก็ตาม ฉันไม่รู้ว่า แต่ดูเหมือนว่าจะถูกเพิ่มนอกท่อ (ในที่สุดฉันต้องใช้ wireshark เพื่อดูมัน)

  2. .NET CORE จะไม่ส่ง "Access-Control-Allow-Origin" ในการตอบกลับเว้นแต่คุณจะมีหัวข้อ "Origin" ในคำขอของคุณ บุรุษไปรษณีย์จะไม่ตั้งค่านี้โดยอัตโนมัติดังนั้นคุณจะต้องเพิ่มด้วยตัวเอง


2

ในกรณีของฉันฉันแก้ไขด้วย UseCors ก่อน UserRouting ..


ฉันพบสิ่งที่คล้ายกันนี้เมื่อฉันอัพเกรดจาก dotnet core 2.2 เป็น 3.1 ต้องย้าย app.UseCors () ด้านบน app.UseRouting () คำตอบนี้ชี้ให้ฉันในทิศทางที่ถูกต้อง
Brandonm

1

.NET Core 3.1

ทำงานให้ฉันและเอกสารบอกว่าจะทำอย่างไร:

ในระดับเริ่มต้น:

readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; 

ในวิธีการ ConfigureServices ():

    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });
    });

ในวิธีการกำหนดค่า ():

    app.UseCors(MyAllowSpecificOrigins);  

https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1


0

ฉันได้รับคำตอบจาก MindingData เพื่อทำงาน แต่ฉันต้องใช้ Microsoft.AspNet.Cors แทน Microsoft.AspNetCore.Cors ฉันใช้โครงการ. NetCore Web Application API ใน Visual Studio 2019


2
หมายเหตุ: คุณไม่ควรใช้ Microsoft.AspNet.Cors ในแอปพลิเคชัน ASP.Net Cor หากคุณใช้งาน. Net Core 3.0 หรือสูงกว่าคุณไม่จำเป็นต้องนำเข้าแพ็คเกจ NuGet ใด ๆ เลยสำหรับ CORS หากคุณใช้. Net Core 2.3 หรือต่ำกว่าคุณต้องใช้ Microsoft.AspNet.Cors รุ่นที่เหมาะสมจาก NuGet
FoggyDay

0

Microsoft.AspNetCore.Cors

จะอนุญาตให้คุณทำ CORS ด้วยคุณสมบัติในตัว แต่ไม่รองรับคำขอ OPTIONS วิธีแก้ปัญหาที่ดีที่สุดคือการสร้าง Middleware ใหม่ตามที่แนะนำในโพสต์ก่อนหน้า ตรวจสอบคำตอบที่ทำเครื่องหมายว่าถูกต้องในโพสต์ต่อไปนี้:

เปิดใช้งานส่วนหัว OPTIONS สำหรับ CORS บน. NET Core Web API


0

วิธีที่ง่ายและสะดวกในการทำ

  1. ติดตั้งแพ็คเกจ

Install-Package Microsoft.AspNetCore.Cors

  1. ใส่รหัสด้านล่างนี้ในไฟล์ startup.cs

app.UseCors(options => options.AllowAnyOrigin());


0

นี่คือรหัสของฉัน:)

  app.Use((ctx, next) =>
        {
            ctx.Response.Headers.Add("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]);
            ctx.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            ctx.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            ctx.Response.Headers.Add("Access-Control-Allow-Headers", "AccessToken,Content-Type");
            ctx.Response.Headers.Add("Access-Control-Expose-Headers", "*");
            if (ctx.Request.Method.ToLower() == "options")
            {
                ctx.Response.StatusCode = 204;

                return Task.CompletedTask;
            }
            return next();
        });

0

นี่คือสิ่งที่ฉันทำ

ฉันเห็นว่าในบางคำตอบพวกเขากำลังตั้งค่าapp.UserCors("xxxPloicy")และ[EnableCors("xxxPloicy")]ควบคุม คุณไม่จำเป็นต้องทำทั้งสองอย่าง

นี่คือขั้นตอน

ใน Startup.cs ภายใน ConfigureServices ให้เพิ่มรหัสต่อไปนี้

    services.AddCors(c=>c.AddPolicy("xxxPolicy",builder => {
        builder.AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader();
    }));

หากคุณต้องการใช้ทั่วทั้งโครงการให้เพิ่มรหัสต่อไปนี้ในวิธีการกำหนดค่าใน Startup.cs

app.UseCors("xxxPolicy");

หรือ

หากคุณต้องการที่จะเพิ่มลงในตัวควบคุมที่เฉพาะเจาะจงแล้วเพิ่มเปิดใช้งานรหัส cors ที่แสดงด้านล่าง

[EnableCors("xxxPolicy")]
[Route("api/[controller]")]
[ApiController]
public class TutorialController : ControllerBase {}

สำหรับข้อมูลเพิ่มเติมดูที่นี่


0

ใช้แอตทริบิวต์ Action / Controller แบบกำหนดเองเพื่อตั้งค่าส่วนหัว CORS

ตัวอย่าง:

public class AllowMyRequestsAttribute : ControllerAttribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        // check origin
        var origin = context.HttpContext.Request.Headers["origin"].FirstOrDefault();
        if (origin == someValidOrigin)
        {
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", origin);
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            // Add whatever CORS Headers you need.
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // empty
    }
}

จากนั้นบน Web API Controller / Action:

[ApiController]
[AllowMyRequests]
public class MyController : ApiController
{
    [HttpGet]
    public ActionResult<string> Get()
    {
        return "Hello World";
    }
}

0

เพียงเพื่อเพิ่มคำตอบที่นี่หากคุณกำลังใช้app.UseHttpsRedirection()งานอยู่และคุณกำลังกดปุ่มไม่พอร์ต SSL ลองแสดงความคิดเห็นนี้


0

ฉันใช้ blazor webassembly เป็น client และ asp.net web api core เป็น backend และมีปัญหาคอร์ด้วย

ฉันพบวิธีแก้ปัญหาด้วยรหัสเหล่านี้:

ASP.Net หลักของฉันเว็บ api Startup.cs ConfigureServices และ Configure เมธอดบรรทัดแรกมีลักษณะดังนี้:

public void ConfigureServices(IServiceCollection services)
{
   services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
   {
        builder.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader();
    }));

 //other code below...
}

และวิธีการกำหนดค่าของฉัน:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseCors(
        options =>   options.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader()
            );
 //other code below...
}

เปลี่ยนhttp://example.comด้วยโดเมนลูกค้าหรือที่อยู่ IP ของคุณ


-1
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddJsonOptions(options => {
                    var resolver = options.SerializerSettings.ContractResolver;
                    if (resolver != null)
                        (resolver as DefaultContractResolver).NamingStrategy = null;
                });

            services.AddDbContext<PaymentDetailContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DevConnection"))); //Dependency Injection
            // options => options.UseSqlServer() Lamda Expression

            services.AddCors(options =>
            {
                options.AddPolicy(MyAllowSpecificOrigins,
                    builder =>
                    {
                        builder.WithOrigins("http://localhost:4200").AllowAnyHeader()
                                .AllowAnyMethod(); ;
                    });
            });

โปรดแก้ไขคำตอบของคุณเพื่อรวมและคำอธิบายของรหัสของคุณและแตกต่างจากคำตอบอื่น ๆ อย่างไร สิ่งนี้จะทำให้การโพสต์ของคุณมีประโยชน์มากขึ้นและมีแนวโน้มที่จะถูกโพสต์มากขึ้น :)
Das_Geek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.