Problem z CORS przy aplikacji webowej działającej lokalnie.

0

Dzień dobry,
testuje sobie lokalnie aplikację webową , gdzie fronted został stworzony za pomocą Reacta, natomiast API za pomocą ASP.NET Core 6.
Mój problem polega na tym że jak uruchamiam aplikacje i chce wykonać polecenie DELETE za pomocą fetch to otrzymuje informacje że nie można pobrać danych ze względu na ograniczenia CORS. Dodam że informacje są wysyłane za pomocą ,,body"
Dodałem już po stronie API opcje https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-6.0, ale niestety nadal mam ten sam problem.

Aplikacja Fronted: localhost:4222
Backend: localhost:5000

Dodałem również do przeglądarki wtyczkę CORS i dla opcji GET oraz INSERT jest ok, a dla DELETE niestety nie działa :(

1

Hostujesz bezpośrednio za pomocą Kestrela, czy masz przed apką jakiegoś IISa, albo coś innego?
Z tego co kojarzę, IIS wymagał oddzielnej konfiguracji po swojej stronie.

0
some_ONE napisał(a):

Hostujesz bezpośrednio za pomocą Kestrela, czy masz przed apką jakiegoś IISa, albo coś innego?
Z tego co kojarzę, IIS wymagał oddzielnej konfiguracji po swojej stronie.

Sam projekt aplikacji był tworzony za pomocą Visual Studio 2022 opcja ASP.NET i React. Jak odpalam fronted to za pomocą dotnet run i wówczas wykonuje się polecenia npm i startuje aplikacja przez proxy, więc możliwe że będzie to Kestrela :)

0
virusek391 napisał(a):

Dodałem również do przeglądarki wtyczkę CORS i dla opcji GET oraz INSERT jest ok, a dla DELETE niestety nie działa :(

Nic nie dodawaj do przeglądarki, to są headery, które serwer ma wysłać do przeglądarki, dzięki temu przeglądarka wie z jakich adresów może wykonywać zapytania pod te api, a z jakich ma nie zezwalać, domyślnie jest nie zezwalaj jeśli adres z jakiego wykonuje się zapytanie jest inny niż adres serwera.

Origins ustawiasz jako adres frontendu, gwiazda zezwala na dowolny adres.

using System.Web.Http;
using System.Web.Http.Cors;

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Enable CORS for all origins, headers, and methods.
        var cors = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(cors);

        // other configuration settings...
    }
}

Można też atrybutem ustawić

using System.Web.Http;
using System.Web.Http.Cors;

[EnableCors("*", "*", "*")]
public class YourApiController : ApiController
{
    // Your controller actions...
}

Akurat nie znam za bardzo c#, kod przekopiowałem do chatGPT.

CORS działa tylko w przeglądarkach jako zabezpieczenie użytkownika, bo tak z innej strony np. evil page, ktoś wyśle do twojego api zapytanie, a http only cookies authoryzujące potwierdzą tożsamość i tak wykonasz niebezpieczne zapytanie hakując użytkowników.
Też nie chroni to wszystkiego, a tylko przed niektórymi atakami.

Jak będą po stronie frontu trzymane credentialse to nic takiego się nie stanie, po to jest CORS, żeby ktoś z obcej strony POST.

0
Autysta napisał(a):
virusek391 napisał(a):

Dodałem również do przeglądarki wtyczkę CORS i dla opcji GET oraz INSERT jest ok, a dla DELETE niestety nie działa :(

Nic nie dodawaj do przeglądarki, to są headery, które serwer ma wysłać do przeglądarki, dzięki temu przeglądarka wie z jakich adresów może wykonywać zapytania pod te api, a z jakich ma nie zezwalać, domyślnie jest nie zezwalaj jeśli adres z jakiego wykonuje się zapytanie jest inny niż adres serwera.

Origins ustawiasz jako adres frontendu, gwiazda zezwala na dowolny adres.

using System.Web.Http;
using System.Web.Http.Cors;

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Enable CORS for all origins, headers, and methods.
        var cors = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(cors);

        // other configuration settings...
    }
}

Można też atrybutem ustawić

using System.Web.Http;
using System.Web.Http.Cors;

[EnableCors("*", "*", "*")]
public class YourApiController : ApiController
{
    // Your controller actions...
}

Akurat nie znam za bardzo c#, kod przekopiowałem do chatGPT.

CORS działa tylko w przeglądarkach jako zabezpieczenie użytkownika, bo tak z innej strony np. evil page, ktoś wyśle do twojego api zapytanie, a http only cookies authoryzujące potwierdzą tożsamość i tak wykonasz niebezpieczne zapytanie hakując użytkowników.
Też nie chroni to wszystkiego, a tylko przed niektórymi atakami.

Jak będą po stronie frontu trzymane credentialse to nic takiego się nie stanie, po to jest CORS, żeby ktoś z obcej strony POST.

Nadal nie działa mi coś :(

Program.cs dla ASP.NET Core (localhost:5000)

    
var  MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy  =>
                      {
                          policy.WithOrigins("http://localhost:44402",
                                              "http://10.0.0.3:44402")
                                              .AllowAnyHeader()
                                              .AllowCredentials()
                                              .AllowAnyMethod();
                      });
});

app.UseCors(MyAllowSpecificOrigins);

Ksiegowosc.cs - Controller - ASP.NET Core

[EnableCors("MyAllowSpecificOrigins")]  
        [HttpDelete("deletebill")]

        public async Task<IActionResult> DeleteBill([FromBody] DeleteRecord body)
        {
            Response.Headers.Add("Access-Control-Allow-Origin", "*");
            Response.Headers.Add("Access-Control-Allow-Headers", "*");
            Response.Headers.Add("Access-Control-Allow-Methods", "DELETE,OPTIONS");
         
            

            var record = await _dbContext.rachunki.FirstOrDefaultAsync(data => data.id == body.id);
            _dbContext.rachunki.Remove(record);
            await _dbContext.SaveChangesAsync();
             var response = new { status = "OK" };
            return Ok(response);
        }

plik program.js dla frontendu (React) (localhost:44402)

fetch(sciezka_bazy + '/deletebill',params)
      .then((response) => response.json())
      .then((result) => {
        if (result.k) {
          Przycisk_Odswiez();
          Swal.fire('Rekord został usunięty!', '', 'success');
        }
      })
      .catch((error) => {
        Swal.fire('Rekord nie został usunięty nie został dodany!', '', 'error');
        console.error('Error:', error);
      });
  }

Na końcu w przeglądarce otrzymuje taki błąd:

Access to fetch at 'http://localhost:5000/ksiegowosc/deletebill' from origin 'http://localhost:44402' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

0

Dziwnie to debugujesz, bo powinieneś jakimś curlem z verbose informacjami wyświetlić zapytanie.
Na początek ustaw wszystko na *.

I preflight request jest wykonywany na http options requescie i ten request status ok powinien zwrócić.

Nie wiem jak w c#, nie korzystam z tego języka w innych frameworkach nigdy z tym nie ma problemu w konfiguracji.

Raczej lepiej analizować na poziomie http niż tylko w logi konsoli patrzeć javascritptu.
Powinieneś też sprawdzić jakie zapytania wysyła http przeglądarka do serwera i co dostaje.

Czyli jakieś proxy możesz sobie podpiąć do analizy.

Pewnie jakiś szczegół został pominięty, który jest wymagany w asp net.

0
Autysta napisał(a):

Dziwnie to debugujesz, bo powinieneś jakimś curlem z verbose informacjami wyświetlić zapytanie.
Na początek ustaw wszystko na *.

I preflight request jest wykonywany na http options requescie i ten request status ok powinien zwrócić.

Nie wiem jak w c#, nie korzystam z tego języka w innych frameworkach nigdy z tym nie ma problemu w konfiguracji.

Raczej lepiej analizować na poziomie http niż tylko w logi konsoli patrzeć javascritptu.
Powinieneś też sprawdzić jakie zapytania wysyła http przeglądarka do serwera i co dostaje.

Czyli jakieś proxy możesz sobie podpiąć do analizy.

Pewnie jakiś szczegół został pominięty, który jest wymagany w asp net.

Dodałem jeszcze rekord za pomocą postmana i tam jest ok
screenshot-20240129142932.png
Nic wieczorkiem trzeba będzie poszukać jeszcze raz :)

1

Pokazałeś POST z Postmana, a wcześniej pisałeś, że problem jest z DELETE.

Poza tym, Postman nigdy się nie wywali na CORS (tak samo jak i curl), bo CORS to zabezpieczenia w przeglądarce.

0
some_ONE napisał(a):

Pokazałeś POST z Postmana, a wcześniej pisałeś, że problem jest z DELETE.

Poza tym, Postman nigdy się nie wywali na CORS (tak samo jak i curl), bo CORS to zabezpieczenia w przeglądarce.

No tak sorry :) Możesz podać mi dokładną nazwę narzędzia które podpowie mi co jest nie tak jeszcze z tym CORS po stronie klienta? Bo pobrałem sobie coś takiego jak curl.

1

Nie znam nic poza przeglądarką.

Możesz też używać Postmana/curla/czegokolwiek do diagnostyki, ale to musiałbyś zrobić request OPTIONS i popatrzeć na zwracane nagłówki - czy jest to czego oczekujesz w nagłówkach Access-Control-*.
Poza tym, upewnij się, że nie podpadasz pod ten scenariusz https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials:~:text=Credentialed%20requests%20and%20wildcards

1
some_ONE napisał(a):

Nie znam nic poza przeglądarką.

Możesz też używać Postmana/curla/czegokolwiek do diagnostyki, ale to musiałbyś zrobić request OPTIONS i popatrzeć na zwracane nagłówki - czy jest to czego oczekujesz w nagłówkach Access-Control-*.
Poza tym, upewnij się, że nie podpadasz pod ten scenariusz https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials:~:text=Credentialed%20requests%20and%20wildcards

Problem rozwiązany :)
Okazało się że podczas wysyłania danych DELETE za pomocą fetch należało dodać nagłówek, w którym umieszczam informacje że dane mają zostać wysłane do mojego API w formacie JSON.

const Usun_Dane_z_Bazy = (id) => {
    const params = {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ id: id }),
    };
    fetch(sciezka_bazy + '/deletebill',params)
      .then((response) => response.json())
      .then((result) => {
        if (result.status) {
          Przycisk_Odswiez();
          Swal.fire('Rekord został usunięty!', '', 'success');
        }

....

1 użytkowników online, w tym zalogowanych: 0, gości: 1