web-dev-qa-db-fra.com

La réponse pour le contrôle en amont n'a pas le statut HTTP ok en angulaire

J'ai la requête suivante de requête définie dans mon service:

createAuthorizationHeader(user, pass) {
  let headers: HttpHeaders = new HttpHeaders;
  headers = headers.append('Accept', 'application/json, text/plain, */*');
  headers = headers.append('Authorization', 'Basic ' + btoa(user + ':' + pass));
  headers = headers.append('Content-Type', 'application/json; charset=utf-8');
    console.log(headers);
    return this.http.get(this._loginUrl, {
      headers: headers
    });
}

Le résultat est:

OPTIONS https://localhost:8443/delivery/all 401 ()

Failed to load https://localhost:8443/delivery/all: Response for preflight does not have HTTP ok status.

HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}

J'ai également fait la même demande de publication avec Postman, mais tout fonctionne, donc le serveur local fonctionne.

Je ne peux pas comprendre ce que je fais mal avec ma demande.

16
KalinJa

Le contrat CORS exige que l'authentification ne soit pas requise pour la demande OPTIONS pré-vol. Il semble que votre serveur nécessite une authentification sur la demande OPTIONS et sur GET.

Lorsque vous accédez à votre back-end avec Postman, vous n’envoyez qu’un message GET . Le navigateur envoie d’abord une demande OPTIONS (sans en-tête d’authentification) et recherche dans la réponse un message «Access-Control-Allow-Allow- "Origine" qui correspond à l’origine de la page faisant la demande.

Si la réponse à la réponse OPTIONS ne correspond pas à 2xx, si l'en-tête n'est pas présent ou si la valeur de l'en-tête ne correspond pas à l'origine de la page demandeuse, vous obtiendrez l'erreur que vous rencontrez et la demande GET ne sera pas effectuée. .

TLDR; changez votre back-end pour ne pas requérir d'authentification pour la méthode OPTIONS lors du traitement de l'URL de connexion.

24
GreyBeardedGeek

Par défaut, les navigateurs n'autorisent pas les utilisateurs à effectuer une requête Cross-Origin.

Depuis Angular pour éviter cette erreur, nous pouvons utiliser la configuration du proxy.

Supposons que si l'interface angulaire fonctionne sur localhost: 4200 et qu'il souhaite appeler l'URL du point final du repos, par exemple: https: // localhost: 8443/delivery/all

Les étapes ci-dessous vont résoudre ce problème.

  1. Créez un fichier proxy.config.json dans le dossier racine de votre application angulaire. (Où le fichier package.json existe) Le proxy consiste simplement à prendre la demande du navigateur dans le même domaine + le même port que celui où votre application frontale est exécutée, puis à la transmettre à votre serveur d'API backend. CORS est un problème de sécurité du navigateur et ne s'applique pas aux communications «back to to backend» comme c'est le cas avec un proxy intermédiaire.

    Le contenu devrait ressembler à ceci.

    Échantillon: 

    {
        "/delivery/all/*": {
        "target": "https://localhost:8443",
        "secure": false,
        "logLevel": "debug",
        "changeOrigin": true
        }
    }
    

    Toutes les demandes faites à/delivery/all/... depuis notre application seront envoyées à https: // localhost: 8443/delivery/all/

    Remarque: la propriété changeOrigin. Vous devrez certainement définir ceci sur true lorsque vous utilisez des proxys virtuels (tels que ceux configurés avec Apache2) sur votre backend

  2. Ajouter une configuration de proxy lors de l'exécution de l'application. Angular prend en charge "--proxy-config", où vous pouvez fournir le fichier de configuration du proxy . Si vous utilisez l'option "npm start" pour les tests, vous devez ajouter l'option "--proxy-config" comme indiqué ci-dessous. Il doit être ajouté dans le fichier package.json.

     "scripts": {
    
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.config.json",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
    }
    

    Si vous utilisez directement en utilisant "ng serve", il doit être modifié comme indiqué ci-dessous . "ng serve --proxy-config proxy.config.json"

  3. L'appel HTTP dans notre application Angular peut être modifié en ceci. Le serveur transmettra automatiquement la demande à " https: // localhost: 8443/delivery/all ".

    this.http.get (' https: // localhost: 8443/delivery/all ') .map (res => res.json ());

    à

    this.http.get ('/ delivery/all') .map (res => res.json ());

voici un lien pour plus d'informations: https://sudhasoftjava.wordpress.com/2018/10/05/proxy-configuration-in-angular/

5
Sudhakar

@Daryl

Nous avons ajouté une configuration personnalisée pour Cors. Puis activez-le via la configuration de sécurité du serveur Java. Ce serveur n'a été activé que pour les appels directs REST, comme expliqué dans la réponse.

@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                        .allowedHeaders("*");
            }
        };
    }
}

Et cela entre dans la configuration de la sécurité Web:

@Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable()
                .antMatcher("/**")
                .authorizeRequests().and()
                .httpBasic()
                .and()
                .authorizeRequests().anyRequest().authenticated().and().cors();
    }
0
thunder88