从存储在本地存储angular + nodejs中的令牌获取用户信息

时间:2018-08-01 21:51:53

标签: node.js angular authentication mongoose

我在正面的我的角度应用程序和背面的NodeJ中使用bcryptjwt进行身份验证。我将令牌存储在用户本地存储中,现在我设法从本地存储中存储和接收令牌,并在刷新后对用户进行身份验证,但是我也想从服务器获取信息,我尝试了几种方法,但我没有确定实现此目标的最佳方法是

我的节点路线

router.post("/login", (req, res, next) => {
    let fetchedUser;
    User.findOne({ email: req.body.email })
      .then(user => {
        console.log(user)
        if (!user) {
          return res.status(401).json({
            message: "Auth failed"
          });
        }
        fetchedUser = user;
        return bcrypt.compare(req.body.password, user.password);
      })
      .then(result => {
        if (!result) {
          return res.status(401).json({
            message: "Auth failed"
          });
        }
        const token = jwt.sign(
          { email: fetchedUser.email, userId: fetchedUser._id },
          "this_is_the_secret",
            { expiresIn: "1h" }
        );
        res.status(200).json({
          token: token,
           expiresIn: 3600,
           isAdmin:fetchedUser.admin,
           user: fetchedUser
        });
      })
      .catch(err => {
        return res.status(401).json({
          message: "Auth failed"
        });
      });
  });

我的服务:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Subject } from "rxjs";
import { Router } from "@angular/router";
import { SignUpData } from "../models/sign-up.model";
import { LogInData } from "../models/log-in.model";


@Injectable({ providedIn: "root"})
export class AuthService {
    private isAuthenticated = false
    private token: string
    private authStatusListner = new Subject<boolean>()
    private tokenTimer: any
    private isAdmin = false
    private userInfo: any

    signupUrl = "http://localhost:3000/signup";
    loginUrl  = "http://localhost:3000/login"

    constructor(private http: HttpClient,
                private router:Router){}

    getToken(){
        return this.token
    }

    checkIfAdmin(){
        return this.isAdmin
    }

    getUserInfo(){
        if(this.token){
            return this.userInfo
        }
    }


    getAuthStatus(){
        return this.isAuthenticated

    }

  getAuthStatusListner(){
      return this.authStatusListner.asObservable()
  }


    createUser(name: string, email: string, password:string){
        const authData: SignUpData = {name:name, email: email, password: password}
        this.http.post(this.signupUrl, authData)
         .subscribe(response => {
         });
    }


    login(email: string, password){
       const authData: LogInData = {email: email, password: password}
        this.http.post<{token: string, expiresIn: number, isAdmin: boolean, user: any}>(this.loginUrl,authData)
        .subscribe(response => {
            const token = response.token
            this.token = token;
            if(token){
                if(response.isAdmin){
                    this.isAdmin = response.isAdmin
                }

                this.userInfo = response.user
                const expiersInDuration = response.expiresIn
                this.setAuthTimer(expiersInDuration)
                this.isAuthenticated = true
                this.authStatusListner.next(true); 
                const now = new Date;
                const expirationDate = new Date (now.getTime() + expiersInDuration * 1000)
                this.saveAuthData(token,expirationDate,this.userInfo.email)  
                this.router.navigate(['/user'])


            }
        });
    }


    // Cheacking if the user have the login token in the local storage for autoLogin and the exparation date 
    autoAuthUser(){
     const AuthInformation =  this.getAuthData()
     if (!AuthInformation){
         return
     }
     const now = new Date();
     const expairesIn = AuthInformation.expirationDate.getTime() - now.getTime();
     if (expairesIn > 0){
         this.token = AuthInformation.token
         this.isAuthenticated = true
         this.setAuthTimer(expairesIn / 1000)
         this.authStatusListner.next(true)
         this.login(AuthInformation.email, AuthInformation.token)
     }
    }

    // User logout
    logout(){
        this.token = null
        this.isAuthenticated = false
        this.isAdmin = false
        this.authStatusListner.next(false) 
        clearTimeout(this.tokenTimer)
        this.clearAuthData()  
        this.router.navigate(['/user'])   

    }


    // Setting the timer for the token expiration
    private setAuthTimer(duration: number){
        this.tokenTimer =  setTimeout(() => {
            this.logout();
        }, duration * 1000)
    }

    // Setting the Auth token in the local storage
    private saveAuthData(token: string, expirationDate: Date, email:string){
        console.log(token)
         localStorage.setItem("email", email )
         localStorage.setItem("token", token)
         localStorage.setItem("expiration", expirationDate.toISOString())
    }

    // Clearing the token from local storage in logout
    private clearAuthData(){
        localStorage.removeItem('email')
        localStorage.removeItem('token')
        localStorage.removeItem('expiration')
    }

    // Geting the login token if it exist in the user local storage
    private getAuthData(){
        const email = localStorage.getItem("email")
        const token = localStorage.getItem("token");
        const expirationDate = localStorage.getItem("expiration")
        if (!token || !expirationDate){
            return
        }
        return {
            email: email,
            token: token,
            expirationDate: new Date(expirationDate)
        }
    }

}

1 个答案:

答案 0 :(得分:0)

实现此功能的标准方法是以与现在相同的方式存储和检索用户令牌。

您的autoAuthUser函数在检索用户令牌后,应使用令牌作为授权标头向服务器发送GET请求(或者,您当前正在为任何授权请求设置令牌)。即

const headers = new Headers({ 'authorization': this.token });
this.http.get<{ user: any }>(this.getUserUrl, { headers }).subscribe(...)

您的后端应根据服务器存储令牌的位置对令牌进行身份验证(我假设是数据库),并返回根据令牌存储的用户信息。您当然不应该使用与登录相同的路由。