Tak, wiem, o czym myślisz - kolejne pytanie CORS-a, ale tym razem jestem zaskoczony.
Na początek rzeczywisty komunikat o błędzie:
XMLHttpRequest nie może załadować http: //localhost/Foo.API/token . Wartość nagłówka „Access-Control-Allow-Origin” w odpowiedzi nie może być symbolem wieloznacznym „*”, gdy tryb poświadczeń żądania to „include” . Dlatego źródło „ http: // localhost: 5000 ” nie ma dostępu. Tryb poświadczeń żądań inicjowanych przez XMLHttpRequest jest kontrolowany przez atrybut withCredentials.
Nie jestem pewien, co oznacza tryb poświadczeń „dołączanie” ?
Kiedy więc wykonuję żądanie w listonoszu, nie ma takiego błędu:
Ale kiedy uzyskuję dostęp do tego samego żądania za pośrednictwem mojej aplikacji internetowej angularjs, jestem zaskoczony tym błędem. Oto moje żądanie / odpowiedź angualrjs. Jak zobaczysz, odpowiedź brzmi OK 200
, ale nadal otrzymuję błąd CORS:
Prośba i odpowiedź Fiddlera:
Poniższy obraz przedstawia żądanie i odpowiedź z frontonu internetowego do interfejsu API
Na podstawie wszystkich innych postów, które przeczytałem w Internecie, wydaje się , że postępuję właściwie, dlatego nie mogę zrozumieć błędu. Na koniec, oto kod, którego używam w angualrjs (fabryka logowania):
Implementacja CORS w API - cele referencyjne:
Zastosowana metoda 1:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
EnableCrossSiteRequests(config);
}
private static void EnableCrossSiteRequests(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*")
{
SupportsCredentials = true
};
config.EnableCors(cors);
}
}
Zastosowana metoda 2:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
Z góry bardzo dziękuję!
źródło
*
- więc strona serwera robi źle CORS - och, a listonosz działa, ponieważ to nie jest prośba o krzyżowe pochodzenieaccess-control-allow-origin
odpowiedź musi być hostem źródłowym (strona przeglądarki), nie może być*
Odpowiedzi:
Problem wynika z twojego kodu Angular:
Gdy
withCredentials
jest ustawiona na true, próbuje wysłać poświadczenia lub pliki cookie wraz z żądaniem. Ponieważ oznacza to, że inne źródło potencjalnie próbuje wykonać uwierzytelnione żądania, symbol wieloznaczny („*”) nie jest dozwolony jako nagłówek „Access-Control-Allow-Origin”.Aby to zadziałało, musiałbyś wyraźnie odpowiedzieć, podając źródło, które wysłało żądanie, w nagłówku „Access-Control-Allow-Origin”.
Zalecałbym jawne umieszczenie na białej liście źródeł, które chcesz zezwolić na wysyłanie uwierzytelnionych żądań, ponieważ po prostu odpowiadanie na źródło z żądania oznacza, że każda dana witryna może wykonywać uwierzytelnione połączenia do twojego zaplecza, jeśli użytkownik ma ważną sesję.
Wyjaśniam to w tym artykule, który napisałem jakiś czas temu.
Możesz więc ustawić
withCredentials
na fałsz lub zaimplementować białą listę pochodzenia i odpowiadać na żądania CORS z prawidłowym źródłem, ilekroć dotyczy to poświadczeńźródło
Jeśli używasz oprogramowania pośredniczącego CORS i chcesz wysłać wartość
withCredentials
logiczną true, możesz skonfigurować CORS w następujący sposób:var cors = require('cors'); app.use(cors({credentials: true, origin: 'http://localhost:5000'}));
`
źródło
Dostosowywanie CORS dla Angular 5 i Spring Security (rozwiązanie bazowe plików cookie)
Po stronie Angular wymagane jest dodanie flagi opcji
withCredentials: true
dla transportu Cookie:constructor(public http: HttpClient) { } public get(url: string = ''): Observable<any> { return this.http.get(url, { withCredentials: true }); }
Po stronie serwera Java wymagane dodanie
CorsConfigurationSource
do konfiguracji zasad CORS:@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // This Origin header you can see that in Network tab configuration.setAllowedOrigins(Arrays.asList("http:/url_1", "http:/url_2")); configuration.setAllowedMethods(Arrays.asList("GET","POST")); configuration.setAllowedHeaders(Arrays.asList("content-type")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and()... } }
Metoda
configure(HttpSecurity http)
domyślnie będzie używanacorsConfigurationSource
dlahttp.cors()
źródło
Jeśli to pomogło, użyłem wirówki z moją aplikacją reagjs i po sprawdzeniu kilku poniższych komentarzy spojrzałem na plik biblioteki centrifuge.js, która w mojej wersji zawierała następujący fragment kodu:
if ('withCredentials' in xhr) { xhr.withCredentials = true; }
Po usunięciu tych trzech linii aplikacja działała dobrze, zgodnie z oczekiwaniami.
Mam nadzieję, że to pomoże!
źródło
Jeśli używasz .NET Core, będziesz musiał .AllowCredentials () podczas konfigurowania CORS w Startup.CS.
Wewnątrz ConfigureServices
services.AddCors(o => { o.AddPolicy("AllowSetOrigins", options => { options.WithOrigins("https://localhost:xxxx"); options.AllowAnyHeader(); options.AllowAnyMethod(); options.AllowCredentials(); }); }); services.AddMvc();
Następnie wewnątrz Configure:
app.UseCors("AllowSetOrigins"); app.UseMvc(routes => { // Routing code here });
U mnie brakowało po prostu opcji AllowCredentials (), które spowodowały wspomniany błąd. Na marginesie, w przypadku innych osób mających również problemy z CORS, kolejność ma znaczenie, a AddCors () musi zostać zarejestrowana przed AddMVC () wewnątrz klasy Startup.
źródło
Po prostu dodaj
Axios.defaults.withCredentials=true
zamiast ({credentials: true}
) po stronie klienta i zmieńapp.use(cors())
naapp.use(cors( {origin: ['your client side server'], methods: ['GET', 'POST'], credentials:true, } ))
źródło