Angular and Node: JWT-аутентификация при прямом доступе с URL к секретному маршруту - PullRequest
0 голосов
/ 12 мая 2018

В моем проекте я использую Angular 5, nodejs, JWT для подписи токенов и passport.js для управления аутентификацией (декодирование токенов).На стороне сервера аутентификация работает хорошо, когда я использую Angular Interceptor, который автоматически устанавливает заголовок при перехвате http-запроса.

Предполагается, что я обращаюсь к / user / profile, который является моим защищенным маршрутомв узле, если я напрямую наберу защищенный маршрут (полный URL http://localhost:3000/user/profile) в браузере, как я могу разрешить уже авторизованному пользователю получить доступ к этой странице вместо неупорядоченного сообщения из passport.js, которое, конечно, может 'я не вижу ни одного токена в заголовке (тело, ни запрос)?

Единственный способ, которым мне удалось это сделать, - создать этот маршрут:

router.get('/isauthenticated', passport.authenticate('jwt', {session: false}), function (req, res) {
res.json({
    id: req.user.id,
    email: req.user.email
});
});

и вызвать его в "ngOnInit" вProfileComponent. Если / isauthenticated проходит хорошо, тогда я позволяю пользователю посетить страницу профиля. Я думаю, что это решение - обходной путь и определенно не элегантный ... поэтому мой вопрос, кроме использования или не passport.js:

возможно ли использовать JWT-аутентификацию с Angular и защитить маршрут с помощью nodejs, а затем разрешить уже аутентифицированному пользователю (который имееттокен, который, конечно, не просрочен) для входа в защищенный маршрут, даже если он напрямую набирает URL в браузере?

Скажите, пожалуйста, даже если вы используете что-то еще вместо passport.js илиесли мне придется использовать другую стратегию.

1 Ответ

0 голосов
/ 20 мая 2018

Вы можете хранить токен jwt внутри локального хранилища браузера.Затем вы можете проверить, не истек ли срок действия этого токена, используя метод tokenNotExpired ().Служба аутентификации должна измениться следующим образом.

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import 'rxjs/add/operator/map';
import { tokenNotExpired } from 'angular2-jwt';
import { NgModule} from '@angular/core';


@Injectable()
export class AuthService {
  authToken: any;
  user: any;

  constructor(private http:Http) { }

  registerUser(user){
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    return this.http.post('https://herokuapp.com/users/register', user,{headers: headers})
      .map(res => res.json());
  }

  authenticateUser(user){
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    return this.http.post('https://herokuapp.com/users/authenticate', user,{headers: headers})
      .map(res => res.json());
  }

  getProfile(){
    let headers = new Headers();
    this.loadToken();
    headers.append('Authorization', this.authToken);
    headers.append('Content-Type', 'application/json');
    return this.http.get('https://herokuapp.com/users/profile',{headers: headers})
      .map(res => res.json());
  }

  storeUserData(token, user){
    localStorage.setItem('id_token', token);
    localStorage.setItem('user', JSON.stringify(user));
    this.authToken = token;
    this.user = user;
  }

  loadToken(){
    const token = localStorage.getItem('id_token');
    this.authToken = token;
  }

  loadUser(){
    const user = localStorage.getItem('user');
  }

  loggedIn() {
    return tokenNotExpired();  //Expired => return false
  }

  logout(){
    this.authToken = null;
    this.user = null;
    localStorage.clear();
  }
}

И login.component.ts должен быть изменен следующим образом

onLoginSubmit() {
    const user = {
      email: this.email,
      password: this.password
    }
    
     
    this.authService.authenticateUser(user).subscribe(data => {
      if (data.success) {
        this.authService.storeUserData(data.token, data.user);
        this.router.navigate(['/pages/dashboard']);
      } else {
        swal(
          'Oops...',
          'Invalid Email or Password..!',
          'error'
        )
        this.router.navigate(['/login']);
        this.password = '';
      }
    });
}

Затем вы можете добавить этот метод ngOnInit () в любой файл component.ts.Если токен хранится в локальном хранилище, то вы можете без проблем перейти на эту страницу. А также вы можете перейти на любую страницу, набрав url следующим образом.(http://localhost:3000/user/profile)

ngOnInit() {
    this.authService.loadToken();
    if(!localStorage.getItem('id_token')){
      this.router.navigate(['/login']);  
    }
}
...