#angular #typescript #ionic-framework #jwt
#angular #typescript #ionic-framework #jwt
Вопрос:
Я работаю над своим первым приложением Ionic и уже выполнил часть аутентификации.
Но после аутентификации, когда я выполняю запрос с использованием HttpClientModule, в заголовке нет токена, и я получаю 401 из моего API, созданного в .net Core.
Я прочитал много сообщений по этой теме, но, похоже, никакое решение не устраняет проблему.
Я не думаю, что проблема в API, потому что он работает на postman, если у вас есть токен на предъявителя в заголовках.
Это моя конфигурация app.module.ts:
import { AuthModule } from './auth/auth.module';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { IonicStorageModule, Storage } from '@ionic/storage';
import { JwtModule, JWT_OPTIONS } from '@auth0/angular-jwt';
export function getAuthScheme(request) {
return 'Bearer ';
}
export function jwtOptionsFactory(storage) {
return {
tokenGetter: () => {
return storage.get('ACCESS_TOKEN');
},
authScheme: getAuthScheme,
whitelistedDomains: ['localhost:44326', 'https://localhost:44326', 'https://localhost:44326/', 'localhost']
};
}
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
AuthModule,
IonicStorageModule.forRoot(),
JwtModule.forRoot({
jwtOptionsProvider: {
provide: JWT_OPTIONS,
useFactory: jwtOptionsFactory,
deps: [Storage],
},
}),
],
providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
],
bootstrap: [AppComponent],
})
export class AppModule {}
Я не проверял параметр использовать cordova при создании приложения. Может быть, это как-то связано с этим?
ОБНОВЛЕНИЕ: Итак, я внедрил перехватчик, как сказал Ронни, но заголовок авторизации по-прежнему не отображается.
app.mmodule.ts такой же, как и раньше, но с этими поставщиками:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptorProvider, multi: true },
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
StatusBar,
SplashScreen,
],
и это мой класс перехватчика:
import { Storage } from '@ionic/storage';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class JwtInterceptorProvider implements HttpInterceptor {
constructor(private storage: Storage) {
console.log(`Hello from JwtInterceptor`);
}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
this.storage.get('ACCESS_TOKEN').then((token) => {
if (token) {
const clonedRequest = this.addToken(request, token);
return next.handle(clonedRequest);
}
});
return next.handle(request);
}
private addToken(request: HttpRequest<any>, token: any) {
if (token) {
console.log(`*******************************************************`);
console.log(`Bearer ${token}`);
const headers = {
Authorization: `Bearer ${token}`,
};
if (request.responseType === 'json') {
console.log('Json request.');
headers['Content-Type'] = 'application/json';
}
console.log('Header added.');
console.log(`*******************************************************`);
return request;
}
}
}
В консоли написано «Добавлен заголовок». таким образом, он достигает кода. Но заголовок не отображается в конечном запросе. Я чувствую, что что-то в приложении перезаписывает заголовки после этого.
Я сейчас действительно в замешательстве. Я ценю любые идеи.
Ответ №1:
Вы должны добавлять токен к каждому запросу. Создайте перехватчик, подтвердите, что у пользователя есть токен, и добавьте его в запрос. Это пример:
// JWT interceptor
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from
'@angular/common/http';
import { Observable } from 'rxjs';
import { AuthenticationService } from '../services/authentication.service';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthenticationService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
const currentAuthToken = this.authenticationService.currentAuthTokenValue;
if (currentAuthToken amp;amp; currentAuthToken.token) {
const headers = {
'Authorization': `Bearer ${currentAuthToken.token}`,
};
if (request.responseType === 'json') {
headers['Content-Type'] = 'application/json';
}
request = request.clone({
setHeaders: headers
});
}
return next.handle(request);
}
}
Вам нужна служба аутентификации для управления вашими пользовательскими данными. В этом примере для этого используется субъект поведения. Обратитесь к этой ссылке для получения дополнительной информации:https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial
Комментарии:
1. Спасибо за ответ! Я внедрил перехватчик, как вы сказали, и проверил все в примере руководства. Но авторизация по-прежнему не отображается в заголовках. Я действительно запутался здесь. Я обновляю код в исходном сообщении.
2. Я думаю, вам не хватает этой строки: request = request.clone({ setHeaders: headers }); Именно здесь заголовок добавляется к запросу.
Ответ №2:
Мне удалось это решить. Проблема была здесь:
this.storage.get('ACCESS_TOKEN').then(...)
Перехватчик игнорировал это обещание и возвращал запрос до того, как .get() был завершен для добавления заголовка.
Я просто сохранил токен в своем классе аутентификации, поэтому он у меня есть в памяти. Я думаю, что перехватчик должен ждать .get(), чтобы сработать.