web-dev-qa-db-fra.com

Angular 6 - Pourquoi manque-t-il un jeton dans la version de production? (fonctionne très bien dans la construction du développeur)

J'utilise Angular 6 avec un intercepteur HTTP configuré pour appliquer un jeton de support aux requêtes sortantes.

  • Dans la version de développement (ng serve), le jeton est appliqué et tout fonctionne correctement. :-)

  • Dans la version de production (ng serve --prod), la demande est envoyée sans jeton de support. :-(

Dans la construction de prod, j'ai vérifié que l'en-tête est appliqué, en vidant les en-têtes sur la console après les avoir appliqués. 

Je ne sais pas pourquoi ils sont exclus de la requête http.

Il n'y a AUCUNE différence dans mes fichiers environment.

Que devrais-je regarder d'autre?

 missing bearer token

Que puis-je faire pour résoudre ce problème?

Au début, j’imaginais que c’était un problème entre mon environnement local et mon environnement de transfert, puis j’ai essayé d’exécuter ng serve --prod localement et j’ai obtenu les mêmes résultats.

Tout cela pour dire, tout est identique sauf un étant une version de production et un étant une version de développement.

jwt-interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class JwtInterceptor implements HttpInterceptor {
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        // add authorization header with jwt token if available
        let currentUser = JSON.parse(localStorage.getItem('currentUser'));

        if (currentUser && currentUser.token) {
            request = request.clone({
                setHeaders: {
                    Authorization: `Bearer ${currentUser.token}`
                }
            });
            console.log('headers:', request.headers); // <---- I can see headers in console output
        }

        return next.handle(request);
    }
}

Voici ce que je vois dans la console:  screenshot of console output

app.module.ts

import { HttpClientModule, HttpClient, HttpInterceptor } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { PortalModule } from '@angular/cdk/portal';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { JwtInterceptor } from './jwt-interceptor';
import { ENV } from '../environments/environment';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
... 
import { myApiService } from './services/my-api.service';
import { myModalComponent } from './_components/my-modal/my-modal.component';
import { myModalService } from './services/my-modal.service';

import { AngularLaravelEchoModule, PusherEchoConfig, EchoInterceptor } from 'angular-laravel-echo/angular-laravel-echo';

export const echoConfig: PusherEchoConfig = {
    userModel: 'App.User',
    notificationNamespace: 'App\\Notifications',
    options: {
        broadcaster: 'pusher',
        key: ENV.pusherConfig.key,
        cluster: ENV.pusherConfig.cluster,
        Host: ENV.apiRoot,
        authEndpoint: ENV.apiRoot + '/broadcasting/auth',
    }
};

@NgModule({
    declarations: [
        AppComponent,
        ...
    ],
    imports: [
        BrowserModule,
        HttpClientModule,
        BrowserModule,
        AppRoutingModule,
        FormsModule,
        ReactiveFormsModule,
        PortalModule,
        AngularLaravelEchoModule.forRoot(echoConfig)
    ],
    providers: [
        myApiService,
        myModalService,
        {
            provide: HTTP_INTERCEPTORS,
            useClass: JwtInterceptor,
            multi: true,
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: EchoInterceptor,
            multi: true
        }
    ],
    bootstrap: [AppComponent],
    entryComponents: [ 
        myModalComponent
    ]
})

export class AppModule {
}
19
BizzyBob

J'ai écrit cette application dans StackBlitz, et tout fonctionne correctement lorsque je l'exécute localement avec ng serve --prod.

https://stackblitz.com/edit/angular-yzckos

Téléchargez-le et lancez-le pour voir si vous obtenez toujours undefined dans l'onglet Réseau. Si vous pouvez voir l'en-tête correctement envoyé, il y a certainement quelque chose de drôle dans votre code.

Essayez ci-dessous: 

1- essayez d’exécuter `ng serve --port = aDifferentPort // like 2098

Peut-être que quelque chose tourne sur ce port et envoie un en-tête auth

2- Essayer avec AOT false, je ne vois pas pourquoi cela causerait des problèmes

3- Assurez-vous que votre navigateur n'a pas d'extension qui remplace l'en-tête Auth ou essayez d'autres navigateurs

4- Eteignez vos autres intercepteurs HTTP, peut-être que l'un d'entre eux fait quelque chose d'inattendu 

5- Modifiez le nom de l'en-tête de Authorizaion à MyAuthorization, voyez si vous êtes toujours indéfini, sinon, il est remplacé par quelque chose, vérifiez votre package.json et assurez-vous de ne rien exécuter d'autre le service de production.

6- Désactivez la variable JwtInterceptor et essayez de joindre l'en-tête d'autorisation à votre demande HTTP afin de voir si vous obtenez toujours undefined.

7- Si rien ne vous aide, vous devez vraiment nous envoyer plus de code :)

1
Milad

J'ai une idée à ce sujet - mais je ne suis pas sûr que cela fonctionne ou non, veuillez vérifier

HttpHeaders sont mutables, si vous ajoutez un en-tête, il met à jour celui existant et ajoute la valeur - cela me cause donc un problème pour ajouter un en-tête, donc j'ai suivi la méthode ci-dessous:

private getHeaders(): HttpHeaders {
    let headers = new HttpHeaders();
    headers = headers.append("Content-Type", "application/json");
    return headers;
  }

Depuis, j’ajoute les nouveaux en-têtes et attribue l’objet à l’objet d’origine et renvoie l’objet - Cela a très bien fonctionné pour moi, à la fois pour les versions prod et dev. 

Mais dans votre cas, vous pouvez utiliser la même méthode que ci-dessus dans votre HttpInterceptor ou essayer de changer la setheaders avec headers comme ci-dessous exemple mentionné

if (currentUser && currentUser.token) {
            request = request.clone({
                headers: new HttpHeaders({
                    Authorization: `Bearer ${currentUser.token}`
                })
            });
            console.log('headers:', request.headers); 
        }

Je suis sûr que cela résoudra votre problème dans les deux versions - essayez de me le faire savoir si cela ne fonctionne pas - j'espère que cela fonctionnera grâce - codage heureux !!

0
Rahul

Pouvez-vous essayer de définir l'en-tête dans l'appel de l'API? Comme, par exemple: 

put(path: string, body: Object = {}): Observable<any> {
return this.http.put(`${environment.api_url}${path}`, body, { headers: 
     this.setHeaders() })
     .map((res: Response) => {
        return res;
     });
}

private setHeaders(): HttpHeaders {
    const headersConfig = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': 'Bearer ' + this.oauthService.getAccessToken()
    };
    return new HttpHeaders(headersConfig);
}

Et l'intercepteur aura juste le 

request.clone() 
0
Minu

Vous pouvez essayer de cloner les en-têtes manuellement dans votre méthode request.clone(). C'est ce qui fonctionne pour moi:

export class HttpHeaderInterceptor implements HttpInterceptor {
  // ...
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // ...
    const clonedRequest = req.clone({ 
      headers: req.headers.set('Authorization', 'Bearer ' + currentUser.token) 
    });
    return next.handle(clonedRequest).pipe(
      catchError(err => { /* Error handling here */ })
    );
  }
}

Espérons que cela aide un peu :-)

0
Heehaaw

J'ai eu presque le problème similaire dans l'environnement de production où le serveur ignore complètement l'en-tête Authorization. Angular 6 envoie correctement l'en-tête Authorization mais le serveur se déshabille complètement (En raison des paramètres de sécurité d'hébergement partagé du serveur de production). Je sais que cela pourrait ne pas être la réponse que vous cherchez. Mais je voulais juste vous donner un indice. 

Donc, enfin, pour que cela fonctionne, je devais utiliser un paramètre d'en-tête différent, tel que Php-Auth-Digest, comme celui-ci. 

request = request.clone({
    setHeaders: {
      "Php-Auth-Digest": `Bearer ${currentUser.token}`,
    }
  });

Pour résoudre ce problème, essayez de modifier le nom de votre paramètre d’en-tête.

À votre santé!

0
Anjana Silva