Как включить CORS в ASP.net основной веб-API



что я пытаюсь сделать



у меня есть бэкэнд ASP.Net основной веб-API, размещенный на свободном плане Azure (http://andrewgodfroyportfolioapi.azurewebsites.net/swagger/) (исходный код:https://github.com/killerrin/Portfolio-Backend).



у меня также есть клиентский сайт, который я хочу сделать потреблять этот API. Клиентское приложение не будет размещено в Azure, а будет размещено на страницах Github или на другом сервере Веб-хостинг, к которому у меня есть доступ. Из-за этого доменные имена не будут выстраиваться.



глядя на это, мне нужно включить CORS на стороне веб-API, однако я пробовал почти все в течение нескольких часов, и он отказывается работать.



как у меня есть настройка клиента
Его просто простой клиент, написанный на реакцию.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 варианта включения его глобально при запуске.cs, настраивая его на каждом контроллере и примеряя его каждое действие.



следуя этому методу, Кросс-домен работает, но только на одном действии на одном контроллере (сообщение в AccountController). Для всего остального,Microsoft.AspNetCore.Cors middleware отказывается устанавливать заголовки.



я установил Microsoft.AspNetCore.Cors через NUGET и версия 1.1.2



вот как я его настроил при запуске.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();

...
...
...
}


[EnableCors("MyPolicy")] на каждом контроллере как так

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




Попытка 2-грубое принуждение его



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



после нескольких часов попыток на предыдущей попытке, я решил, что я попытаюсь bruteforce его, пытаясь установить заголовки вручную, заставляя их работать на каждый ответ. Я сделал это после этого урока о том, как вручную добавлять заголовки к каждому ответу.



это заголовки, которые я добавил



.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")


С помощью этого метода заголовки перекрестных сайтов применяются правильно, и они отображаются в моей консоли разработчика и в Postman. Проблема, однако, в том, что в то время как он проходит Access-Control-Allow-Origin проверьте, webbrowser бросает шипящий припадок на (Я считаю)Access-Control-Allow-Headers о том,415 (Unsupported Media Type)



так метод грубой силы тоже не работает





наконец-то



кто-нибудь получил это работать и может протянуть руку, или просто быть в состоянии указать мне в правильном направлении?





EDIT



поэтому, чтобы получить вызовы API, мне пришлось прекратить использовать JQuery и переключиться на чистый Javascript .



Попытка 1



мне удалось получить Microsoft.AspNetCore.Cors чтобы работать, следуя ответу MindingData, за исключением Configure способ поставить app.UseCors до app.UseMvc.



кроме того, при смешивании с решением Javascript API 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"));
3147   7  

7 ответов:

потому что у вас есть очень простая политика CORS (разрешить все запросы из домена XXX), вам не нужно делать это так сложно. Сначала попробуйте выполнить следующее (Очень простая реализация CORS).

Если вы еще этого не сделали, установите пакет CORS nuget.

Install-Package Microsoft.AspNetCore.Cors

в методе ConfigureServices вашего запуска.cs, добавьте службы CORS.

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

затем в вашем методе настройки вашего запуска.cs, добавьте следующее :

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCors(
        options => options.WithOrigins("http://example.com").AllowAnyMethod()
    );

    app.UseMvc();
}

сейчас попробую. Политики предназначены для тех случаев, когда вам нужны разные политики для разных действий (например, разные хосты или разные заголовки). Для вашего простого примера вам это действительно не нужно. Начните с этого простого примера и настроить, как вам нужно оттуда.

дальнейшее чтение:http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/

  • на ConfigureServices добавить services.AddCors();до службы.AddMvc ();
  • добавить UseCors в настроить

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

главное, что добавить app.UseCors до app.UseMvc().

убедитесь, что вы объявили функциональность CORS перед MVC, чтобы промежуточное программное обеспечение срабатывало до того, как конвейер MVC получит контроль и завершит запрос.

Я создал свой собственный класс middleware, который работал для меня, я думаю, что что-то не так с .net core middleware class

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>();
    }
}

и использовал его таким образом в стартап.cs

app.UseCorsMiddleware();

только в моем случае get запрос хорошо работает в соответствии с ответом MindingData. Для других типов запросов вам нужно написать:

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

не забудьте добавить .AllowAnyHeader()

попробуйте добавить 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
    }),

расширить на user8266077 ' s ответ, я обнаружил, что мне все еще нужно было предоставить варианты ответа для предварительные запросы в .NET Core 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);
  }
}

а затем включил промежуточное программное обеспечение, как и при запуске.cs

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

основываясь на вашем комментарии в ответе MindingData, он не имеет ничего общего с вашим CORS, он работает нормально.

действие контроллера возвращает неверные данные. HttpCode 415 означает "неподдерживаемый тип носителя". Это происходит, когда вы либо передаете неправильный формат контроллеру (т. е. XML контроллеру, который принимает только json), либо когда вы возвращаете неправильный тип (возвращаете Xml в контроллере, который объявлен только для возврата xml).

для более поздней проверки существования [Produces("...")]атрибут на вашем действии

Comments

    Ничего не найдено.