在 Angular 中维护身份验证状态/会话

时间:2021-05-07 13:06:48

标签: angular

我尝试了多种方法来实现这一点,我的问题是当我第一次登录时,用户界面没有反映我已登录。我必须刷新页面才能显示我的个人资料图片/用户名。< /p>

API:

router.get('/login', (req, res) => {
    if (req.user) {
        const token = jwt.sign({ userId: req.user.user_id, discordId: req.user.discord_id },
            process.env.COOKIE_SECRET);
        res.status(200).json({
            token: token,
            expiresIn: 3600,
            user: req.user
        });
    } else {
        res.send('not logged in!')
    }

});

router.get('/signedin', isAuthorized, (req, res) => {
    if (req.user) {
        res.json({
            authenticated: true,
            user_id: req.user.discord_id
        });
    } 
});

我的服务:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { BehaviorSubject, Subject } from 'rxjs';
import { Router } from '@angular/router';
import { CommonService } from '../service/common.service';
import { tap } from 'rxjs/operators';

interface SignedinResponse {
  authenticated: boolean;
  user_id: string;
}

@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {
  signedin$ = new BehaviorSubject(false);

  private userInfo: any;
  private userId: string;
  private discordId: string;
  private token: string;
  private tokenTimer: any;
  private isAuthenticated = false;
  public authStatusListener = new Subject<boolean>();
  constructor(private http: HttpClient,
    private router: Router,
    private commonService: CommonService) { }

  getToken() {
    return this.token;
  }

  getIsAuth() {
    return this.isAuthenticated;
  }

  getUserId() {
    return this.userId;
  }

  getUserInfo() {
    return this.userInfo
  }

  getDiscordId() {
    return this.discordId;
  }

  getAuthStatusListener() {
    return this.authStatusListener.asObservable();
  }

  login() {
    this.commonService.showLoadingOverlay();
    return this.http.get('/auth/login/').subscribe((data: any) => {
      const token = data.token;
      this.token = token;
      if (token) {
        this.signedin$.next(true);
        this.userInfo = data.user;
        this.userId = data.user.user_id;
        this.discordId = data.user.discord_id;
        this.authStatusListener.next(true);
        this.isAuthenticated = true;
        const expiresInDuration = data.expiresIn;
        const now = new Date();
        const expirationDate = new Date(now.getTime() + expiresInDuration * 10000);
        this.saveAuthData(token, expirationDate, this.userId, this.userInfo);
        this.setAuthTimer(expiresInDuration);

        this.commonService.hideLoadingOverlay();
        this.router.navigate(['/']);
      }
    }, error => {
      this.commonService.hideLoadingOverlay();
      this.router.navigate(['/'])
      const message = 'Not logged in...'
      this.commonService.showErrorMessage(message);
    }

    )
  }

  private saveAuthData(token: string, expirationDate: Date, userId: string, userInfo: any) {
    localStorage.setItem("token", token);
    localStorage.setItem("expiration", expirationDate.toISOString());
    localStorage.setItem("userId", userId);
    localStorage.setItem("userInfo", JSON.stringify(userInfo));
  }

  private clearAuthData() {
    localStorage.removeItem("token");
    localStorage.removeItem("expiration");
    localStorage.removeItem("userId");
    localStorage.removeItem("userInfo");
  }

  autoAuthUser() {
    const authInformation = this.getAuthData();
    if (!authInformation) {
      return;
    }
    const now = new Date();
    const expiresIn = authInformation.expirationDate.getTime() - now.getTime();
    if (expiresIn > 0) {
      this.token = authInformation.token;
      this.isAuthenticated = true;
      this.userId = authInformation.userId;
      this.userInfo = authInformation.userInfo;
      this.setAuthTimer(expiresIn / 1000);
      this.authStatusListener.next(true);
    }
  }

  private setAuthTimer(duration: number) {
    this.tokenTimer = setTimeout(() => {
      this.logout();
    }, duration * 1000);
  }


  private getAuthData() {
    const token = localStorage.getItem("token");
    const expirationDate = localStorage.getItem("expiration");
    const userId = localStorage.getItem("userId");
    const userInfo = JSON.parse(localStorage.getItem("userInfo"));
    if (!token || !expirationDate) {
      return;
    }
    return {
      token: token,
      expirationDate: new Date(expirationDate),
      userId: userId,
      userInfo: userInfo
    }
  }


  logout() {
    this.commonService.showLoadingOverlay();
    this.token = null;
    this.isAuthenticated = false;
    this.authStatusListener.next(false);
    this.userId = null;
    this.userInfo = null;
    clearTimeout(this.tokenTimer);
    this.clearAuthData();
    this.router.navigate(["/"]);

    return this.http.get('/auth/logout').subscribe((data: any) => {
      this.signedin$.next(false);
      this.commonService.hideLoadingOverlay();
      this.commonService.showSuccessMessage('Logged out!');
    }, error => {
      this.commonService.hideLoadingOverlay();
      this.commonService.showErrorMessage('Please refresh the page.');
    })

  }

  checkAuth() {
    return this.http
      .get<SignedinResponse>(`/auth/signedin`)
      .pipe(
        tap(({ authenticated }) => {
          this.signedin$.next(authenticated);
        })
      );
  }

}

获取不和谐用户服务:

getDiscordUser() {
   return this.http.get<{id: string, avatar: string, username:string}>('/discordapi/user/');
}

component.ts :

import { Component, OnDestroy, OnInit } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { AuthenticationService } from '../core/authentication/authentication.service';
import { ShellService } from './shell.service';
import { CommonService } from '../core/service/common.service';
import { Router } from '@angular/router';

@Component({
    selector: 'app-shell',
    templateUrl: './shell.component.html',
    styleUrls: ['./shell.component.scss']
})
export class ShellComponent implements OnInit {
    signedin = false;
    userId: any;
    userInfo: any;
    discordUser: any;
    isAdmin = false;
    roleList;

    constructor(private breakpointObserver: BreakpointObserver,
        private authService: AuthenticationService,
        private shellService: ShellService,
        private commonService: CommonService,
        private router: Router) { }

      ngOnInit() {
this.authService.signedin$.subscribe(signedin => {
  this.signedin = signedin;
  console.log(this.signedin);
  this.userInfo = this.authService.getUserInfo();
  //Get Discord User
  this.commonService.getDiscordUser().subscribe((data: any) => {
    console.log(data);
    this.discordUser = data;
    if (this.signedin && this.userInfo) {
      this.checkUser();
    }
  }, error => {
    this.commonService.showErrorMessage(error.message);
    this.commonService.hideLoadingOverlay();
  });

}, error => {
  this.commonService.hideLoadingOverlay();
  this.commonService.showErrorMessage(error);
})
this.authService.checkAuth().subscribe(() => { });

}

    checkUser() {
        this.commonService.showLoadingOverlay();

        // Check role
        this.shellService.getRole().subscribe((data: any) => {
            this.roleList = data.role;
            if (this.roleList.some(e => e.admin_code === this.userInfo.discord_id)) {
                this.isAdmin = true;
            }
            this.commonService.hideLoadingOverlay();
        }, error => {
            this.commonService.showErrorMessage(error.message);
            this.commonService.hideLoadingOverlay();
        });
    }

    onLogout() {
        this.authService.logout();
        this.isAdmin = false;
    }

    }

该应用在登录时不保持登录状态,我必须在登录后刷新页面才能看到我已登录

0 个答案:

没有答案