Токен-носитель авторизации Angular 5

Я не понимаю, как создать хороший заголовок для простого запроса Get в Angular 5.

Вот что мне нужно сделать в Angular: Токен-носитель авторизации Angular 5

Вот что у меня есть на данный момент:

  getUserList(): Observable<UserList[]> {
    const headers = new Headers();
    let tokenParse = JSON.parse(this.token)             
    headers.append('Authorization', `Bearer ${tokenParse}`);
    const opts = new RequestOptions({ headers: headers });  
    console.info(JSON.stringify(opts));
    const users = this.http.get<UserList[]>(this.mainUrl, opts)
    return users
            .catch(this.handleError.handleError);         
  }

Это ответ в моем журнале console.info:

{"method":null,"headers":{"Authorization":["Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImYwODZlM2FiYTk0ZjVhMjVmNDhiNzlkYmI2YWUwOWY4YzE2MTUyMzg2N2I5MDZiY2MzNWQyNWJiYTZmYTE4YjEwZjA1MjZiNThkZjE2Y2FjIn0.eyJhdWQiOiJmMDExY2M1OC00MGNlLTQzYTktOGY3MS04NDI0OTRlM2E5OTciLCJqdGkiOiJmMDg2ZTNhYmE5NGY1YTI1ZjQ4Yjc5ZGJiNmFlMDlmOGMxNjE1MjM4NjdiOTA2YmNjMzVkMjViYmE2ZmExOGIxMGYwNTI2YjU4ZGYxNmNhYyIsImlhdCI6MTUyMzU1MTQ0NSwibmJmIjoxNTIzNTUxNDQ1LCJleHAiOjE1MjM1NTQ0NDUsInN1YiI6IjIiLCJzY29wZXMiOlsiYXV0aGVudGljYXRlZCIsImFuZ3VkcnUiXX0.E-WdQTl7nPDW0gj0rohfql-QgnAinzvDxPR-pySMrG07XFY9tA6Ex7IL23pDBmKDmQO8RcZKa0L5r6SRQq9_iqzMWzn5Zxp94J9TJrpZ2KGMoLR_FbK_tpC5G5q5vUnCe3q34sH7cPdT_2cI704OWWaYmIUKKpXWUIG0PJw_uKSJ_uOifPv59RZGQkoaQ9gPywDKe-uamm1Faug-Kk2YnFMoEJq7ou19zyxgdpX80ZTPUae67uB0PGLRuvxfGaqVsJ8k0NunAY3-pyUnBwR_3eeuOxf4TyfW2aiOJ9kuPgsfV4Z1JD7nMpNtTHMJaXEyNkBW8RlYHD1pj4dkdnsDmw"]},"body":null,"url":null,"withCredentials":null,"responseType":null}

Смотрится красиво. Но дает мне эту ошибку

GET http://druang.dd:8080/user-list?_format=json 403 (Forbidden)

Есть еще один ключ к разгадке этой загадки. В Sublime text, если я наведу указатель мыши на opts, он скажет что-то вроде:

ERROR in src/app/services/userlist.service.ts(33,59): error TS2345: Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'. Types of property 'headers' are incompatible. Type 'Headers' is not assignable to type 'HttpHeaders | { [header: string]: string | string[]; }'. Type 'Headers' is not assignable to type '{ [header: string]: string | string[]; }'. Index signature is missing in type 'Headers'.

Любая идея?? Вот полный Репозиторий Git Спасибо за вашу помощь!

Я думаю, вы импортируете неправильный класс для заголовков, попробуйте проверить документацию angular в версии 5, служба http устарела для службы httpClient, но httpClient находится в @ angular / common, а другой - в @ angular / http, вы не можете смешивать классы из те вызывают ошибки. На мой взгляд, ваши ошибки выглядят так, будто вы используете http из «@ angular / common» и заголовки из «@ angular / http» вместо HttpHeaders из «@ angular / common»

Nicu 12.04.2018 19:03

Привет, спасибо @Nicu, это мой импорт: import { HttpClient, HttpHeaders } from '@angular/common/http'; в соответствии с угловым документация

ValRob 12.04.2018 19:08

Отлично: D @ angular / http он будет заменен на @ angular / common / http, удаленный в ng 6, я полагаю.

Nicu 12.04.2018 21:17
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
33
3
81 082
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Две вещи:

  1. headers.append(...) не изменяет объект заголовков, поэтому ваш заголовок авторизации не отправляется. Нужно делать headers = headers.append(...)

  2. Попробуйте this.http.get<UserList[]>(this.mainUrl, { headers: headers });

1) headers = headers.append дает мне: невозможно назначить заголовки, потому что это константа или свойство только для чтения

ValRob 12.04.2018 19:07

либо измените объявление с const headers на let headers`, либо сделайте const headers = new Headers().append('Authorization', Bearer $ {tokenParse} `);

GreyBeardedGeek 12.04.2018 19:11

С let он сказал: Type void is not assignable to type 'Headers'

ValRob 12.04.2018 19:16

Другой вариант работает, но когда я установил const opts = new RequestOptions({ headers: headers });, я получил: ERROR in src/app/services/userlist.service.ts(33,37): error TS2345: Argument of type '{ headers: void; }' is not assignable to parameter of type 'RequestOptionsArgs'. Types of property 'headers' are incompatible. Type 'void' is not assignable to type 'Headers'.

ValRob 12.04.2018 19:17

Кроме того, если я забыл о параметрах и сразу перейду к {headers:headers} в HTTP-запросе на получение, я получу следующее: ERROR in src/app/services/userlist.service.ts(35,59): error TS2345: Argument of type '{ headers: void; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'. Types of property 'headers' are incompatible. Type 'void' is not assignable to type 'HttpHeaders | { [header: string]: string | string[]; }'.

ValRob 12.04.2018 19:18

Я нашел решение ... Если вы можете мне объяснить, спасибо !. const users = this.http.get<UserList[]>(this.mainUrl, { headers:new HttpHeaders().set('Authorization', Bearer $ {tokenParse} )})

ValRob 12.04.2018 19:34

Я не очень хорош в программировании, но с небольшими попытками и неудачами если нашел это:

  getUserList(): Observable<UserList[]> {
    let tokenParse = JSON.parse(this.token)    
    // let myHeaders = new Headers();
    // myHeaders.set('Authorization', `Bearer ${tokenParse}`);
    // let options = new RequestOptions({ headers: myHeaders});
    const users = this.http.get<UserList[]>(this.mainUrl, { headers:new HttpHeaders().append('Authorization', `Bearer ${tokenParse}`)})
    // const users = this.http.get<UserList[]>(this.mainUrl, options);
    return users
            .catch(this.handleError.handleError);         
  }

На самом деле не имеет значения, использую ли я .set или .append, в конце концов, он работает в обоих случаях ...

Я действительно не знаю, что происходит, поэтому, если кто-то хочет объяснить это в комментариях, милости просим ...

Ответ принят как подходящий

Я предлагаю использовать HttpInterceptor для установки заголовков HTTP по умолчанию для исходящих запросов, а не добавлять дополнительный заголовок HTTP к каждому вызову.

HTTP-клиент - установка заголовков по умолчанию @ angular.io


В вашем примере вы можете сделать следующее:

import { Http, Headers, Response } from '@angular/http';

getLoggedInUser(auth_token): Observable<any> {
  const headers = new Headers({
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${auth_token}`
  })
  return this.http.get(apiUrl, { headers: headers })
}

Просто чтобы добавить, токен должен быть добавлен к «предъявителю», поэтому в вашем примере это будет «авторизация»: Bearer ${auth_token}

Alator 30.06.2019 19:23

Мне нужно было использовать HttpHeaders, а не Headers, но после этого все заработало. ?

Jim 14.10.2020 23:44

Для запросов get я использовал следующий код, и он работает

import { HttpClient, HttpHeaders } from '@angular/common/http';

getServerList(){
    var reqHeader = new HttpHeaders({ 
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + JSON.parse(localStorage.getItem('mpManagerToken'))
     });
    return this.http.get<Server[]>(`${environment.apiUrl}/api/Servers/GetServerList`, { headers: reqHeader });
}

В Angular 6 и 7 этот метод можно использовать для перехвата всех HTTP-запросов и добавления токена-носителя.

Руководство по внедрению доступно здесь. YouTube, на этом канале есть все обучающие программы.

Компонент перехватчика

import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpUserEvent,
  HttpEvent
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { UserService } from '../shared/user.service';
import { tap } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private router: Router) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    if (req.headers.get('No-Auth') === 'True') {
      return next.handle(req.clone());
    }

    if (localStorage.getItem('userToken') != null) {
      const clonedreq = req.clone({
        headers: req.headers.set(
          'Authorization',
          'Bearer ' + localStorage.getItem('userToken')
        )
      });
      return next.handle(clonedreq).pipe(
        tap(
          succ => {},
          err => {
            if (err.status === 401) {
              // this.router.navigateByUrl('/login');
            } else if ((err.status = 403)) {
              // this.router.navigateByUrl('/forbidden');
              // alert(err.localStorage.getItem('userToken'));
            }
          }
        )
      );
    } else {
      this.router.navigateByUrl('/login');
    }
  }
}

Компонент защиты

import { Injectable } from '@angular/core';
import {
  CanActivate,
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
  Router
} from '@angular/router';
import { Observable } from 'rxjs';
import { UserService } from '../shared/user.service';
import { ToastrService } from 'ngx-toastr';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private router: Router,
    private userService: UserService,
    private toastr: ToastrService
  ) {}
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    if (localStorage.getItem('userToken') != null) {
      const roles = next.data['roles'] as Array<string>;
      if (roles) {
        const match = this.userService.roleMatch(roles);
        if (match) {
          return true;
        } else {
          // tslint:disable-next-line: quotemark
          this.toastr.info("You don't have access to this page");
          this.router.navigate(['/login']);
          // this.router.navigate(['/forbidden']);
          return false;
        }
      } else {
        return true;
      }
    }
    this.router.navigate(['/login']);
    return false;
  }
}

Добавьте его в app.modules.ts

providers: [
    ConfirmationDialogService,
    UserService,
    DoctorService,
    { provide: OwlDateTimeIntl, useClass: DefaultIntl },
    { provide: OWL_DATE_TIME_FORMATS, useValue: MY_MOMENT_FORMATS },
    AuthGuard,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true
    }
  ],

Затем к маршруту добавляется охранник.

 {
    path: 'adminPanel',
    component: AdminPanelComponent,
    canActivate: [AuthGuard],
    data: { roles: ['Admin'] }
  },
'Authorization': 'Bearer ' + access_token,

это сработало

Хотя @HassanRahman показывает это для запросов get, для запросов post,

import { HttpClient, HttpHeaders } from '@angular/common/http';

getServerList(){

    postData = { your data }
    var reqHeader = new HttpHeaders({ 
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + JSON.parse(localStorage.getItem('mpManagerToken'))
     });
    return this.http.post<Server[]>(`${environment.apiUrl}/api/Servers/GetServerList`, postData, { headers: reqHeader });
}

Другие вопросы по теме