shivangkaul Ответов: 4

Проблема CORS, когда angular и web API(.NET core) используется [решено]


У меня есть два отдельных проекта, Один из которых WebAPI разработан в .net Core 2.2 с аутентификацией Windows, а другой-Angular. Я застрял в вопросе CORS. Я смог обработать запрос GET с помощью withCredentials: true в опции метода GET, как указано ниже, где httpClient - это импорт { HttpClient } из '@angular/common/http':
httpClient.get('url'), { withCredentials: true }) as Observable<Type>;

Но в случае POST запрос идет как опция. И каждый раз он терпит неудачу с кодом ошибки 401 UNAUTHORIZED на вкладке Network окна Chrome Developer Tools. И в консоли он показывает следующую ошибку

Доступ к XMLHttpRequest по адресу 'http://localhost:5000/api/xxx/xxxMethod" от происхождения "http://localhost:4200' был заблокирован политикой CORS: ответ на предполетный запрос не проходит проверку контроля доступа: он не имеет статуса HTTP ok.

Что я уже пробовал:

Чтобы решить эту проблему, я внес несколько изменений в следующие файлы Web API и Angular project:

Веб.конфиг:Я добавил приведенный ниже код под тегом system.webserver
<handlers>
   <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
   <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
   <remove name="OPTIONSVerbHandler" />
   <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<httpProtocol>
   <customHeaders>
     <add name="Access-Control-Allow-Origin" value="http://localhost:4200" />
     <add name="Accept" value="application/json, text/plain, */*"/>
   </customHeaders>
</httpProtocol>


PreflightRequestMiddleware.в CS: Я создал это промежуточное программное обеспечение для обработки всех входящих запросов и обхода запроса опций со статусом OK
public class PreflightRequestMiddleware
{
  private readonly RequestDelegate Next;
  public PreflightRequestMiddleware(RequestDelegate next)
  {
    Next = next;
  }
  public Task Invoke(HttpContext context)
  {
    return BeginInvoke(context);
  }
  private Task BeginInvoke(HttpContext context)
  {
    context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
    context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept, Athorization, ActualUserOrImpersonatedUserSamAccount, IsImpersonatedUser" });
    context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
    if (context.Request.Method == HttpMethod.Options.Method)
    {
      context.Response.StatusCode = (int)HttpStatusCode.OK;
      return context.Response.WriteAsync("OK");
    }
    return Next.Invoke(context);
  }
}

public static class PreflightRequestExtensions
{
  public static IApplicationBuilder UsePreflightRequestHandler(this IApplicationBuilder builder)
  {
    return builder.UseMiddleware<PreflightRequestMiddleware>();
  }
}


Автозагрузки.в CS:
public void ConfigureServices(IServiceCollection services)
{
  services.AddCors(o => o.AddPolicy("CorePolicy", builder =>
  {
    builder.AllowAnyMethod();
  }));
  .......
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UsePreflightRequestHandler();
  .....
  app.UseCors("CorePolicy"); //Tried to put this first line too, but no luck
  .....
}


Then in Angular Project, for POST method call I first create headers:
<pre lang="TypeScript">
HttpHeaders() with below values:
'Content-Type', 'application/json'
'Content-Type', 'application/json'
'Accept-Language', ['en-US', 'en', 'q=0.9']
'Accept', ['application/json', 'text/plain', '*/*']
'Athorization', 'Include'

Calling POST Method
client.post(url, postParam, optionsWithHeader).pipe(
            map((response: any) => response as Result[]),
            catchError(#HandleError)


Но есть одна странная вещь, которую я заметил, Когда я сначала запускаю Fiddler, а затем запускаю Web API и Angular app, все запросы опций обрабатываются в PreflightRequestMiddleware. Но когда я бегу без скрипача, запрос даже не доходит до PreflightRequestMiddleware. Я провел 4 дня, но до сих пор понятия не имею, что случилось. Мало кто может предложить мне проверить заголовок, который получается при запуске Fiddler in Request, но я тоже попробовал это сделать, но безуспешно. У кого-нибудь есть хоть малейшая зацепка??

Mahadevan Annamalai

Решение 1 - это решение моей проблемы. Спасибо за сообщение.

4 Ответов

Рейтинг:
30

shivangkaul

Наконец, я смог выяснить, как решить вышеупомянутую проблему. Поскольку я не могу ответить на свой собственный вопрос здесь, поэтому я публикую решение здесь:

Решение: Я удалил весь вышеприведенный код и начал все заново, как уже упоминалось ниже с файлами:

Автозагрузки.в CS:

public void ConfigureServices(IServiceCollection services)
{
  services.AddCors(options =>
  {
    options.AddPolicy(
      "CorsPolicy",
      builder => builder.WithOrigins("http://localhost:4200")
      .AllowAnyMethod()
      .AllowAnyHeader()
      .AllowCredentials());
    });
  services.AddAuthentication(IISDefaults.AuthenticationScheme);
  .....
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UseCors("CorsPolicy");

  app.UsePreflightRequestHandler();
  .......
}


launchSettings.в JSON: Я аноним и проверку подлинности Windows для истинного
{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:5000",
      "sslPort": 0
    }
  },
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "TPIGO.WebAPI": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5000"
    }
  }
}


Затем, в угловом:
//For GET & POST

Add, withCredentials: true as otions


Теперь приходит объяснение этому решению.

Как я уже упоминал в своем заявлении о проблеме, запрос GET работал нормально, но проблема была с запросом POST.

В случае POST-запроса браузер сначала отправлял запрос опций для аутентификации на сервере, но этот запрос никогда не достигнет сервера, и именно по этой причине я не смог обработать запрос в PreflightRequestMiddleware.

Запрос опций не удался, потому что API был настроен для проверки подлинности Windows, а запрос опций не нес с собой никакой проверки подлинности.

Именно по этой причине я включил анонимную аутентификацию в launchSettings.json.

Но когда я включил анонимную аутентификацию, я начал получать 500 внутренних ошибок сервера, и, исследуя его дальше, я пришел к выводу, что мне нужно предоставить схему аутентификации.

Затем я добавил услуги.AddAuthentication(IISDefaults.AuthenticationScheme); в методе Startup.cs files ConfigureServices(IServiceCollection services). и все работает как по волшебству.

Не забудьте добавить withCredentials: true с каждым запросом, который вы отправляете в API, который нуждается в аутентификации.

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

ЗАПИСКА: Я все еще использую PreflightRequestMiddleware только для того, чтобы сделать некоторые дополнительные вещи по запросу и ответу, но это промежуточное программное обеспечение не требуется.
public class PreflightRequestMiddleware
    {
        private readonly RequestDelegate Next;

        public PreflightRequestMiddleware(RequestDelegate next)
        {
            Next = next;
        }

        public Task Invoke(HttpContext context)
        {
            return BeginInvoke(context);
        }

        private Task BeginInvoke(HttpContext context)
        {
            // Do stuff here
            return Next.Invoke(context);
        }
    }

    public static class PreflightRequestExtensions
    {
        public static IApplicationBuilder UsePreflightRequestHandler(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<PreflightRequestMiddleware>();
        }
    }


Member 14558413

Куда девается эта угловая часть?

Могу ли я добавить его в файл ts?

Спасибо


AbstractReadOnlyService.httpHeaders = new HttpHeaders().set('Content-Type', 'application/json');
AbstractReadOnlyService.httpHeaders = AbstractReadOnlyService.httpHeaders.установить('принять', 'приложение/JSON');

AbstractReadOnlyService.optionsStatic = {
заголовки: AbstractReadOnlyService.httpHeaders,
параметры: новые HttpParams(),
withCredentials: true
};

//Для получения
вернуть это.с помощью HttpClient.вам(это.getWebApiServiceUrl('/applicationusers/папка'), { параметры: этот.httpParams, withCredentials: истина }), поскольку наблюдаемые в<Профиль пользователя&ГТ;;

//на должности
верните this.httpClient.post(url, firmDashboardSearchCriteria, AbstractReadOnlyService.optionsStatic).pipe(
map((response: any) => response as xxxxSearchResult[]),
catchError(это.handleerror с)

Mahadevan Annamalai

в файле Angular yourService.ts, как показано ниже

this.http.get(your URL',{withCredentials: true}).pipe(
карту((РЭС: любой) =&ГТ; {РЭС; консоли.журналов ("успех"); консоль.журнал(ВИЭ);}),
catchError(<t>(ошибка: есть, результат?: T) => {
консоли.лог ("ошибка"); консоль.войти(ошибка);
возвращение(результат, как Т);
})
);

tripe3way

шивангкаул , Чувак , ты такой отличный разработчик , твое решение спасло меня примерно после 6 часов непрерывной работы, я тебе очень обязан, могу ли я получить твой linkedin и обещаю, что если ты живешь в Северной Америке, я приглашу тебя на пиво и ужин
СПАСИБО

[no name]

Спасибо, это именно то, с чем я боролся. Мне просто нужно было включить анонимную аутентификацию, и почтовые запросы снова начали работать.

Рейтинг:
1

Member 14874844

У меня такая же проблема с asp.net ядро 3.1 и угловой 9.
Решение, которое вы проиллюстрировали, в моем случае не работает.

Я все время получаю одну и ту же ошибку:
"Доступ к XMLHttpRequest по адресу 'http://localhost:5000/api/......" от начала "http://localhost:4200' был заблокирован политикой CORS: ответ на предполетный запрос не проходит проверку контроля доступа: на запрашиваемом ресурсе отсутствует заголовок 'Access-Control-Allow-Origin'."

Я также заметил, что во время отладки для запросов GET обрабатывается класс PreflightRequestMiddleware, в то время как когда речь заходит о запросах опций, это не так.


Рейтинг:
0

jprimavera13

Это работает для меня:

Web.config

<httpProtocol>
  <customHeaders>
	<add name="Access-Control-Allow-Origin" value="*" />
	<add name="Access-Control-Allow-Methods" value="*" />
	<add name="Access-Control-Allow-Headers" value="x-requested-with, Content-Type, origin, authorization, accept, client-security-token" />
  </customHeaders>
</httpProtocol>  

Global.asax

protected void Application_BeginRequest()
{
	if (Request.Headers.AllKeys.Contains("Origin") && 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, PUT, DELETE");
		HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
		HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
		HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
		HttpContext.Current.Response.End();
	}
}


Рейтинг:
0

Member 14946965

Hola buenas tardes, en este fragmento de codigo

builder => builder.WithOrigins("http://localhost:4200")
remplazo por el puerto de mi localhost?


CHill60

Компания si desea Хаджер отель una pregunta, использовать Эл обвивать Рохо 'задать вопрос' в Ла парте улучшенный-де-ла-страница.
Debe escribirlo en inglés en este sitio por favor. Utilice la herramienta 'Traductor de Google'