Đặt Access-Control-allow-Origin trong ASP.Net MVC - phương pháp đơn giản nhất có thể


206

Tôi có một hành động đơn giản, trả về một số json. Nó chạy trên ajax.example.com. Tôi cần truy cập trang này từ một trang khác someothersite.com.

Nếu tôi cố gắng gọi nó, tôi sẽ nhận được ...

Origin http://someothersite.com is not allowed by Access-Control-Allow-Origin.

Tôi biết hai cách để giải quyết vấn đề này: JSONP và tạo một httpHandler tùy chỉnh để đặt tiêu đề.

Có cách nào đơn giản hơn không?

Có phải là một hành động đơn giản để xác định một danh sách các nguồn gốc được phép - hoặc đơn giản cho phép tất cả mọi người? Có lẽ một bộ lọc hành động?

Tối ưu sẽ là ...:

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);

1
Xin hãy xem vNext và MVC6 tại đây: neelbhatt40.wordpress.com/2015/09/10/ Ấn
Neel

Câu trả lời:


381

Đối với bộ điều khiển ASP.NET MVC đơn giản

Tạo một thuộc tính mới

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}

Gắn thẻ hành động của bạn:

[AllowCrossSiteJson]
public ActionResult YourMethod()
{
    return Json("Works better?");
}

Đối với API Web ASP.NET

using System;
using System.Web.Http.Filters;

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null)
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");

        base.OnActionExecuted(actionExecutedContext);
    }
}

Gắn thẻ toàn bộ bộ điều khiển API:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{

Hoặc các lệnh gọi API riêng lẻ:

[AllowCrossSiteJson]
public IEnumerable<PartViewModel> Get()
{
    ...
}

Dành cho Internet Explorer <= v9

IE <= 9 không hỗ trợ CORS. Tôi đã viết một javascript sẽ tự động định tuyến các yêu cầu đó thông qua proxy. Tất cả đều minh bạch 100% (bạn chỉ cần bao gồm proxy của tôi và tập lệnh).

Tải xuống bằng nuget corsproxyvà làm theo các hướng dẫn đi kèm.

Bài đăng trên blog | Mã nguồn


8
Kinh ngạc! Tôi luv MVC + U!
Piotr Kula

2
trong sự kinh ngạc của sự thanh lịch của giải pháp này
BraveNewMath

3
Bạn có thể dễ dàng mở rộng thuộc tính để chấp nhận một nguồn gốc cụ thể nếu bạn muốn giới hạn CORS cho các miền của riêng bạn.
Petrus Theron

2
Bạn có thể thêm cái này vào RegisterHttpFilters trong App_Start \ FilterConfig của bạn đúng không? Làm như vậy sẽ áp dụng nó cho tất cả các bộ điều khiển Api trong dự án của bạn. Kết hợp điều này với nhận xét của pate ở trên, bạn có thể giới hạn CORS cho (các) tên miền của mình cho tất cả các bộ điều khiển.
bdwakefield

9
Gần đây tôi đã cập nhật dự án của chúng tôi lên MVC 5 và đã cố gắng thực hiện điều này. Ngay cả việc thêm tiêu đề trong bộ lọc dường như không hoạt động. Khi tôi xem yêu cầu trong mạng, tiêu đề không xuất hiện trên phản hồi. Có bất cứ điều gì khác cần phải làm để có được điều này để làm việc?
Kneemin

121

Nếu bạn đang sử dụng IIS 7+, bạn có thể đặt tệp web.config vào thư mục gốc của thư mục này trong phần system.webServer:

<httpProtocol>
   <customHeaders>
      <clear />
      <add name="Access-Control-Allow-Origin" value="*" />
   </customHeaders>
</httpProtocol>

Xem: http://msdn.microsoft.com/en-us/l Library / ms178685.aspx Và: http://enable-cors.org/#how-iis7


1
Tôi không thể nhớ tại sao nữa, nhưng phương pháp này không phải lúc nào cũng hoạt động trong IIS 7+
LaundroMatt

Hừm. Lý do duy nhất tôi có thể nghĩ rằng nó sẽ không hoạt động là nếu một yêu cầu bắt nguồn từ trình duyệt không phải CORS. Nhưng tôi sẽ tiếp tục điều tra.
sellmeadog

29
Ngoài ra, điều này sẽ làm cho toàn bộ trang web thân thiện với CORS. Nếu ai đó muốn chỉ đánh dấu một hành động hoặc bộ điều khiển duy nhất là thân thiện với CORS, thì câu trả lời được chấp nhận sẽ tốt hơn nhiều.
Lev Dubinets

1
Nếu bạn thấy phần ASP.Net , nó có một gợi ý : "Lưu ý: phương pháp này tương thích với IIS6, Chế độ cổ điển IIS7 và Chế độ tích hợp IIS7."
Nhận thức

1
Tôi đang gặp vấn đề về tên miền chéo khi tôi xuất bản ứng dụng của mình trên môi trường SharePoint. Khi tôi chạy ứng dụng của mình trên môi trường cục bộ, ứng dụng của tôi chạy tốt, nhưng khi tôi xuất bản nó trên azure lên trang sharepoint của mình, nó sẽ chuyển hướng đến trang lỗi trong cuộc gọi mẫu Ajax.Begin. Tôi đã thử giải pháp này nhưng nó không hiệu quả với tôi. Có sự thay thế nào khác cho nó?
Jyotsna Wadhwani

22

Tôi gặp phải một vấn đề trong đó trình duyệt từ chối cung cấp nội dung mà nó đã truy xuất khi yêu cầu được gửi trong cookie (ví dụ: xhr có withCredentials=true) và trang web đã được Access-Control-Allow-Originđặt *. (Lỗi trong Chrome là "Không thể sử dụng ký tự đại diện trong Kiểm soát truy cập-Cho phép-Xuất xứ khi cờ thông tin xác thực là đúng.")

Dựa trên câu trả lời từ @jgauffin, tôi đã tạo ra cái này, về cơ bản là một cách làm việc xung quanh việc kiểm tra bảo mật trình duyệt cụ thể đó, vì vậy hãy cẩn thận.

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // We'd normally just use "*" for the allow-origin header, 
        // but Chrome (and perhaps others) won't allow you to use authentication if
        // the header is set to "*".
        // TODO: Check elsewhere to see if the origin is actually on the list of trusted domains.
        var ctx = filterContext.RequestContext.HttpContext;
        var origin = ctx.Request.Headers["Origin"];
        var allowOrigin = !string.IsNullOrWhiteSpace(origin) ? origin : "*";
        ctx.Response.AddHeader("Access-Control-Allow-Origin", allowOrigin);
        ctx.Response.AddHeader("Access-Control-Allow-Headers", "*");
        ctx.Response.AddHeader("Access-Control-Allow-Credentials", "true");
        base.OnActionExecuting(filterContext);
    }
}

Điều này đặc biệt hữu ích, cảm ơn bạn.
cklimowski

15

Điều này thực sự đơn giản, chỉ cần thêm cái này vào web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="http://localhost" />
      <add name="Access-Control-Allow-Headers" value="X-AspNet-Version,X-Powered-By,Date,Server,Accept,Accept-Encoding,Accept-Language,Cache-Control,Connection,Content-Length,Content-Type,Host,Origin,Pragma,Referer,User-Agent" />
      <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" />
      <add name="Access-Control-Max-Age" value="1000" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Trong Origin đặt tất cả các tên miền có quyền truy cập vào máy chủ web của bạn, trong các tiêu đề đặt tất cả các tiêu đề có thể mà bất kỳ yêu cầu ajax http nào cũng có thể sử dụng, trong các phương thức đặt tất cả các phương thức mà bạn cho phép trên máy chủ của mình

Trân trọng :)


Thêm "Ủy quyền" trong Kiểm soát truy cập-Cho phép-Tiêu đề cũng có thể hữu ích nếu bạn có ý định sử dụng truy vấn được ủy quyền.
Thu hút

9

Đôi khi động từ TÙY CHỌN cũng gây ra vấn đề

Đơn giản là: Cập nhật web.config của bạn bằng cách sau

<system.webServer>
    <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Allow-Origin" value="*" />
          <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

Và cập nhật các tiêu đề webservice / bộ điều khiển với httpGet và httpOptions

// GET api/Master/Sync/?version=12121
        [HttpGet][HttpOptions]
        public dynamic Sync(string version) 
        {

BTW, trong trang web, bạn cần thêm * vào cài đặt nâng cao của Hệ thống trong phần bảo mật
Bishoy Hanna

các tập tin mà tôi cần để cập nhật các tiêu đề của bộ điều khiển là gì?
dùng3281466


5

Thêm dòng này vào phương thức của bạn, Nếu bạn đang sử dụng API.

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 

4

Hướng dẫn này rất hữu ích. Để tóm tắt nhanh:

  1. Sử dụng gói CORS có sẵn trên Nuget: Install-Package Microsoft.AspNet.WebApi.Cors

  2. Trong WebApiConfig.cstệp của bạn , thêm config.EnableCors()vào Register()phương thức.

  3. Thêm một thuộc tính cho bộ điều khiển bạn cần để xử lý cors:

[EnableCors(origins: "<origin address in here>", headers: "*", methods: "*")]


Tôi đã phải sử dụng phương pháp này vì tôi cần đặt tiêu đề tùy chỉnh trong yêu cầu của mình và phương thức thuộc tính tùy chỉnh không hoạt động với yêu cầu trước chuyến bay của trình duyệt. Điều này dường như làm việc trong tất cả các trường hợp.
lehn0058

3
    public ActionResult ActionName(string ReqParam1, string ReqParam2, string ReqParam3, string ReqParam4)
    {
        this.ControllerContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");
         /*
                --Your code goes here --
         */
        return Json(new { ReturnData= "Data to be returned", Success=true }, JsonRequestBehavior.AllowGet);
    }

2

Có nhiều cách khác nhau để chúng ta có thể vượt qua Tiêu đề kiểm soát truy cập.

  • Như jgauffin đã giải thích, chúng ta có thể tạo một thuộc tính mới.
  • Như LaundroMatt đã giải thích, chúng tôi có thể thêm vào tệp web.config.
  • Một cách khác là chúng ta có thể thêm mã như dưới đây trong tệp webApiconfig.cs.

    config.EnableCors (new EnableCorsAttribution (" ", tiêu đề: " ", phương thức: "*", phơi bàyHeaders: "TestHeaderToExpose") {SupportCredentials = true});

Hoặc chúng ta có thể thêm mã dưới đây vào tệp Global.Asax.

protected void Application_BeginRequest()
        {
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                //These headers are handling the "pre-flight" OPTIONS call sent by the browser
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
                HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "TestHeaderToExpose");
                HttpContext.Current.Response.End();
            }
        }

Tôi đã viết nó cho các tùy chọn. Vui lòng sửa đổi giống như theo nhu cầu của bạn.

Chúc mừng mã hóa !!


1

Sau khi vật lộn cả buổi tối, cuối cùng tôi cũng có được việc này. Sau khi gỡ lỗi, tôi thấy vấn đề tôi gặp phải là khách hàng của tôi đã gửi một yêu cầu Tùy chọn preflight để kiểm tra xem ứng dụng có được phép gửi yêu cầu bài đăng với nguồn gốc, phương thức và tiêu đề được cung cấp không. Tôi không muốn sử dụng Owin hoặc APIControll, vì vậy tôi bắt đầu đào và tìm ra giải pháp sau chỉ với ActionFilterAttribution. Đặc biệt là phần "Kiểm soát truy cập-Cho phép-Tiêu đề" rất quan trọng, vì các tiêu đề được đề cập ở đó phải phù hợp với các tiêu đề mà yêu cầu của bạn sẽ gửi.

using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MyNamespace
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpRequest request = HttpContext.Current.Request;
            HttpResponse response = HttpContext.Current.Response;

            // check for preflight request
            if (request.Headers.AllKeys.Contains("Origin") && request.HttpMethod == "OPTIONS")
            {
                response.AppendHeader("Access-Control-Allow-Origin", "*");
                response.AppendHeader("Access-Control-Allow-Credentials", "true");
                response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                response.End();
            }
            else
            {
                HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                HttpContext.Current.Response.Cache.SetNoStore();

                response.AppendHeader("Access-Control-Allow-Origin", "*");
                response.AppendHeader("Access-Control-Allow-Credentials", "true");
                if (request.HttpMethod == "POST")
                {
                    response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                    response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                }

                base.OnActionExecuting(filterContext);
            }
        }
    }
}

Cuối cùng, phương thức hành động MVC của tôi trông như thế này. Điều quan trọng ở đây là cũng đề cập đến các Tùy chọn httpVerbs, vì nếu không, yêu cầu preflight sẽ không thành công.

[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
    return Json(await DoSomething(model));
}

0

Trong Web.config, nhập thông tin sau

<system.webServer>
<httpProtocol>
  <customHeaders>
    <clear />     
    <add name="Access-Control-Allow-Credentials" value="true" />
    <add name="Access-Control-Allow-Origin" value="http://localhost:123456(etc)" />
  </customHeaders>
</httpProtocol>

0

Nếu bạn sử dụng IIS, tôi khuyên bạn nên thử mô-đun IIS CORS .
Thật dễ dàng để cấu hình và hoạt động cho tất cả các loại bộ điều khiển.

Dưới đây là một ví dụ về cấu hình:

    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="*" />
            <add origin="https://*.microsoft.com"
                 allowCredentials="true"
                 maxAge="120"> 
                <allowHeaders allowAllRequestedHeaders="true">
                    <add header="header1" />
                    <add header="header2" />
                </allowHeaders>
                <allowMethods>
                     <add method="DELETE" />
                </allowMethods>
                <exposeHeaders>
                    <add header="header1" />
                    <add header="header2" />
                </exposeHeaders>
            </add>
            <add origin="http://*" allowed="false" />
        </cors>
    </system.webServer>

0

Tôi đang sử dụng DotNet Core MVC và sau vài giờ chiến đấu với các gói nuget, Startup.cs, thuộc tính và địa điểm này, tôi chỉ cần thêm nó vào hành động MVC:

Response.Headers.Add("Access-Control-Allow-Origin", "*");

Tôi nhận ra điều này khá là rắc rối, nhưng đó là tất cả những gì tôi cần, và không có gì khác muốn thêm những tiêu đề đó. Tôi mong điều này giúp được người nào khác!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.