Angular 6 - Почему токен на предъявителя отсутствует в производственной сборке? (отлично работает в dev build)
Я использую Angular 6 с HTTP-перехватчиком, настроенным на применение токена-носителя для исходящих запросов.
В сборке prod я убедился, что заголовок применяется, выгрузив заголовки на консоль после их применения.
Я понятия не имею, почему они исключены из запроса http.
В моих файлах environment
НЕТ различий.
На что еще я должен смотреть?
Что я могу сделать, чтобы это исправить?
Сначала я думал, что это проблема между моей локальной средой и моей промежуточной средой, но затем я попытался запустить ng serve --prod
локально и увидел те же результаты.
Все это говорит о том, что все идентично, за исключением одного, являющегося производственной сборкой, а другой - разработкой.
JWT-перехватчик:
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);
}
}
Вот что я вижу в консоли:
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 {
}
Ответы
Ответ 1
Я написал это приложение в StackBlitz, и оно работает нормально, когда я запускаю его локально с ng serve --prod
.
https://stackblitz.com/edit/angular-yzckos
Загрузите его и запустите, чтобы увидеть, не появилось ли еще undefined
на вкладке сети. Если вы видите, что заголовок отправляется правильно, то в вашем коде определенно есть что-то смешное.
Попробуйте ниже:
1- попробуйте запустить 'ng serve --port = aDifferentPort//как 2098
Может быть, что-то работает на этом порту и отправляет заголовок аутентификации
2- Попробуй с AOT false, не могу придумать, почему это может вызвать проблемы
3- Убедитесь, что в вашем браузере нет расширения, которое перекрывает заголовок Auth, или попробуйте другие браузеры.
4- Отключите ваши другие перехватчики HTTP, возможно, один из них делает что-то неожиданное
5- Измените имя заголовка с Authorizaion
на MyAuthorization
, посмотрите, если вы по-прежнему получаете неопределенное значение, если нет, то оно будет переопределено чем-то, проверьте ваш package.json
и убедитесь, что вы больше ничего не запускаете на производственной подаче.
6- Полностью отключите JwtInterceptor
и попробуйте присоединить заголовок авторизации к вашему HTTP
запросу, посмотрите, по-прежнему ли вы получаете undefined
.
7- Если никто не помог, вам действительно нужно отправить нам больше кода :)
Ответ 2
У меня была почти аналогичная проблема в производственной среде, где сервер полностью игнорирует заголовок Authorization
. Angular 6 отправляет заголовок Authorization
правильно, но сервер полностью удаляется (из-за большей части рабочего сервера, параметры безопасности общего хостинга). Я знаю, что это может быть не тот ответ, который вы ищете. Но я просто хотел дать вам подсказку.
Итак, наконец, чтобы я заработал, мне пришлось использовать другой параметр заголовка, такой как Php-Auth-Digest
, например, так.
request = request.clone({
setHeaders: {
"Php-Auth-Digest": 'Bearer ${currentUser.token}',
}
});
В качестве обходного пути попробуйте изменить имя параметра заголовка.
Ура!
Ответ 3
Можете ли вы попробовать установить заголовок в реальном вызове API? Как, например:
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);
}
И перехватчик будет иметь только
request.clone()
Ответ 4
Вы можете попробовать клонировать заголовки вручную в вашем методе request.clone()
. Это то, что работает для меня:
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 */ })
);
}
}
Надеюсь, это немного поможет :-)
Ответ 5
У меня есть идея по этому поводу - но я не уверен, что это может сработать или нет, пожалуйста, проверьте
HttpHeaders
являются изменяемыми, если вы добавляете какой-либо заголовок, он обновляет существующий и добавляет значение - так что это вызывает у меня проблему с добавлением заголовка, поэтому следуйте приведенному ниже методу:
private getHeaders(): HttpHeaders {
let headers = new HttpHeaders();
headers = headers.append("Content-Type", "application/json");
return headers;
}
Так как я добавляю новые заголовки и назначаю объект исходному объекту и возвращаю объект - у меня это хорошо работало как в prod, так и в dev build
Но в вашем случае вы можете использовать тот же метод, что и выше, в вашем HttpInterceptor
или попытаться изменить headers
setheaders
как setheaders
в примере ниже.
if (currentUser && currentUser.token) {
request = request.clone({
headers: new HttpHeaders({
Authorization: 'Bearer ${currentUser.token}'
})
});
console.log('headers:', request.headers);
}
Я уверен, что это решит вашу проблему в обеих сборках - попробуйте и дайте мне знать, если это не сработает - надеюсь, это сработает, спасибо - счастливого кодирования !!
Ответ 6
Попробуй это
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: 'Bearer ${currentUser.token}'
}
});
console.log('headers:', request.headers); // <---- I can see headers in console output
}
if (typeof $ != 'undefined') {
$.ajaxSetup({
beforeSend: function (xhr: any) {
xhr.setRequestHeader('Authorization', 'Bearer ' + currentUser.token);
}
});
}
return next.handle(request);