CORS: le mode des informations d'identification est 'inclure'

100

Oui, je sais ce que vous pensez - encore une autre question CORS, mais cette fois je suis perplexe.

Donc, pour commencer, le message d'erreur réel:

XMLHttpRequest ne peut pas charger http: //localhost/Foo.API/token . La valeur de l'en-tête «Access-Control-Allow-Origin» dans la réponse ne doit pas être le caractère générique «*» lorsque le mode des informations d' identification de la demande est «inclure» . L' accès à l' origine ' http: // localhost: 5000 ' n'est donc pas autorisé. Le mode d'informations d'identification des demandes initiées par XMLHttpRequest est contrôlé par l'attribut withCredentials.

Je ne suis pas sûr que le mode d'identification signifie «inclure» ?

Ainsi, lorsque j'effectue la demande dans Postman, je ne rencontre pas une telle erreur:

entrez la description de l'image ici

Mais lorsque j'accède à la même requête via mon application Web angularjs, je suis perplexe face à cette erreur. Voici ma demande / réponse angualrjs. Comme vous le verrez, la réponse est OK 200, mais je reçois toujours l'erreur CORS:

Demande et réponse de Fiddler:

L'image suivante montre la demande et la réponse du front-end Web à l'API

Violoneux

Donc, sur la base de tous les autres articles que j'ai lus en ligne, il semble que je fais la bonne chose, c'est pourquoi je ne comprends pas l'erreur. Enfin, voici le code que j'utilise dans angualrjs (login factory):

entrez la description de l'image ici

Implémentation CORS dans l'API - Objectifs de référence:

Méthode 1 utilisée:

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

Méthode 2 utilisée:

public void Configuration(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();

    ConfigureOAuth(app);

    WebApiConfig.Register(config);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(config);

}

Merci d'avance!

Richard Bailey
la source
belles photos, de quoi s'agit-il? Pour répondre à votre question, si vous incluez l'authentification, la réponse access-control-allow-origin doit être l'hôte d'origine (page du navigateur), elle ne peut pas être *- donc, le côté serveur fait mal CORS - oh, et le facteur fonctionne parce que ce n'est pas une demande d'origine croisée
Jaromanda X
@JaromandaX, merci pour la réponse. Les images montrent la demande / réponse ainsi que les en-têtes passés. Vous posez la question, affirme évidemment qu'il n'a pas atteint son objectif ...
Richard Bailey
Mon commentaire devrait être tout ce que vous devez savoir - pas besoin de voir les photos
Jaromanda X
Récemment, j'ai décidé de m'éloigner des cookies sur mon API Web et d'utiliser plutôt des jetons. Lorsque j'utilise des cookies, mon CORS fonctionne sans aucun problème. J'ai donc du mal à comprendre comment CORS n'est pas implémenté correctement côté serveur
Richard Bailey
1
si vous incluez l'authentification, la access-control-allow-originréponse doit être l'hôte d'origine (page du navigateur), elle ne peut pas être*
Jaromanda X

Réponses:

103

Le problème provient de votre code angulaire:

Lorsque withCredentialsest défini sur true, il essaie d'envoyer des informations d'identification ou des cookies avec la demande. Comme cela signifie qu'une autre origine essaie potentiellement de faire des demandes authentifiées, le caractère générique ("*") n'est pas autorisé comme en-tête "Access-Control-Allow-Origin".

Vous devrez répondre explicitement avec l'origine qui a fait la demande dans l'en-tête "Access-Control-Allow-Origin" pour que cela fonctionne.

Je recommanderais de mettre explicitement sur liste blanche les origines que vous souhaitez autoriser pour effectuer des demandes authentifiées, car le simple fait de répondre avec l'origine de la demande signifie que tout site Web donné peut passer des appels authentifiés à votre backend si l'utilisateur a une session valide.

J'explique ce truc dans cet article que j'ai écrit il y a quelque temps.

Vous pouvez donc définir withCredentialssur false ou implémenter une liste blanche d'origine et répondre aux demandes CORS avec une origine valide chaque fois que des informations d'identification sont impliquées

geekonaut
la source
3
Je travaille sur l'application Angular 5 avec TypeScript. Je dois donner withCredentials comme vrai sinon j'obtiendrai l'exception d'échec d'autorisation. Comment résoudre ce problème avecCredentials: true
Ziggler
@Ziggler J'ai eu la même situation. Trouvez-vous des solutions?
Pavel
@Ziggler J'ai infligé une amende à la solution, voir ma réponse.
Pavel
1
J'obtiens toujours cette erreur lorsque j'utilise WithCredentials = TRUE et Access-Control-Allow-Origin = [' localhost: 4200'] , et je n'utilise PAS star * donc le message d'erreur n'a plus de sens. MESSAGE D'ERREUR: "La réponse à la demande de contrôle en amont ne passe pas la vérification de contrôle d'accès: la valeur de l'en-tête" Access-Control-Allow-Origin "dans la réponse ne doit pas être le caractère générique * lorsque le mode des informations d'identification de la demande est" include ". Origine ' localhost: 4200 ' n'est donc pas autorisé à accéder. Le mode d'identification des requêtes initiées par XMLHttpRequest est contrôlé par l'attribut withCredentials. "
mruanova
@mruanova êtes-vous sûr que l'en-tête Access-Control-Allow-Origin est correctement défini dans la demande? On dirait que quelque chose est envoyé avec un joker quelque part
geekonaut
14

Si vous utilisez le middleware CORS et que vous voulez envoyer withCredentialsboolean true, vous pouvez configurer CORS comme ceci:

var cors = require('cors');    
app.use(cors({credentials: true, origin: 'http://localhost:5000'}));

»

Ankur Kedia
la source
3
Réponse de Gareautrain. +1 pour cela
Nisharg Shah
1
J'ai essayé de résoudre ce problème toute la journée. Vous êtes le sauveur!
Hasan Sefa Ozalp
11

Personnalisation de CORS pour Angular 5 et Spring Security (solution de base de cookies)

Du côté angulaire, il fallait ajouter un indicateur d'option withCredentials: truepour le transport des cookies:

constructor(public http: HttpClient) {
}

public get(url: string = ''): Observable<any> {
    return this.http.get(url, { withCredentials: true });
}

Sur le côté serveur Java, ajout requis CorsConfigurationSourcepour la configuration de la stratégie 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()...
    }
}

La méthode configure(HttpSecurity http)par défaut utilisera corsConfigurationSourcepourhttp.cors()

Pavel
la source
1

Si cela aide, j'utilisais une centrifugeuse avec mon application reactjs et, après avoir vérifié quelques commentaires ci-dessous, j'ai regardé le fichier de bibliothèque centrifuge.js, qui dans ma version, contenait l'extrait de code suivant:

if ('withCredentials' in xhr) {
 xhr.withCredentials = true;
}

Après avoir supprimé ces trois lignes, l'application a bien fonctionné, comme prévu.

J'espère que cela aide!

Gustavo Garcia
la source
Merci ... cela m'a fait gagner beaucoup de temps! :)
pavan kumar chaitanya
1

Si vous utilisez .NET Core, vous devrez .AllowCredentials () lors de la configuration de CORS dans Startup.CS.

À l'intérieur de ConfigureServices

services.AddCors(o => {
    o.AddPolicy("AllowSetOrigins", options =>
    {
        options.WithOrigins("https://localhost:xxxx");
        options.AllowAnyHeader();
        options.AllowAnyMethod();
        options.AllowCredentials();
    });
});

services.AddMvc();

Puis à l'intérieur de Configure:

app.UseCors("AllowSetOrigins");
app.UseMvc(routes =>
    {
        // Routing code here
    });

Pour moi, c'était précisément des options manquantes.AllowCredentials () qui ont causé l'erreur que vous avez mentionnée. Comme note latérale en général pour les autres ayant des problèmes CORS, l'ordre est important et AddCors () doit être enregistré avant AddMVC () à l'intérieur de votre classe Startup.

Steven Pfeifer
la source