angular + nodejs 控制台显示“GET http://localhost:4200/user/profile 401 (Unauthorized)”

Posted

技术标签:

【中文标题】angular + nodejs 控制台显示“GET http://localhost:4200/user/profile 401 (Unauthorized)”【英文标题】:angular + nodejs console shows "GET http://localhost:4200/user/profile 401 (Unauthorized) " 【发布时间】:2020-10-20 06:58:18 【问题描述】:

我正在尝试在登录后将数据存储到 /profile。但是,我在登录后一直在控制台中收到这 2 个错误。

"VM276:1 GET http://localhost:4200/user/profile 401 (未授权)" 和“HttpErrorResponse headers: HttpHeaders, status: 401, statusText: "Unauthorized"”。

由于我遵循不同的教程来解决这个问题,所以我知道我在令牌代码上犯了一些错误,我只是不知道如何修复它。我要感谢任何花时间提供帮助的人!这是我的 authentication.service.ts

import  Injectable  from '@angular/core';
import HttpClient from "@angular/common/http";
import Observable, of from 'rxjs';
import  map  from 'rxjs/operators';
import Router from '@angular/router';


export interface UserDetails
  username: string
  email: string
  password: string
  exp: number
  iat: number

interface TokenResponse
  token: string

export interface TokenPayload
  username: string
  email: string
  password: string

@Injectable(
  providedIn: 'root'
)
export class AuthenticationService 
  private token: string

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

  private saveToken(token: string): void
    localStorage.setItem('usertoken', token)
    this.token = token
  
  private getToken(): string
    if(!this.token)
      this.token = localStorage.getItem('usertoken')
    
    return this.token
  
  public getUserDetails(): UserDetails
    const token = this.getToken()
    let payload
    if(token)
      payload = token.split('.')[1]
      payload = window.atob(payload)
      return JSON.parse(payload)
    else
      return null
    
  
  public isLoggedIn(): boolean
    const user = this.getUserDetails()
    if(user)
      return user.exp > Date.now()/ 1000
    
    else
      return false
    
  
  public login(user: TokenPayload): Observable<any>
    const base = this.http.post('/user/login', user)
    const request = base.pipe(
      map((data: TokenResponse) => 
        if(data.token)
          this.saveToken(data.token)
        return data
      )
    )
    return request
  
  public register(user: TokenPayload) : Observable<any>
    const base = this.http.post('/user/register', user)
    const request = base.pipe(
      map((data: TokenResponse) => 
        if(data.token)
          this.saveToken(data.token)
        
        return data
      )
    )
    return request
  
  public profile(): Observable<any>
    return this.http.get('/user/profile',
      headers: Authorization: `$this.getToken()`
    )
  
  public logout(): void
    this.token = ''
    window.localStorage.removeItem('usertoken')
    this.router.navigateByUrl('/')
  


这是我的 profile.component.ts

export class ProfileComponent implements OnInit 

  details: UserDetails

  constructor(private auth: AuthenticationService) 

  ngOnInit() 
    this.auth.profile().subscribe(
      user => 
        this.details = user
      ,
      err => 
        console.error(err)
      
    )
  

这是我的 auth.js

const jwt = require("jsonwebtoken");

module.exports = function(req, res, next) 
  const token = req.header("token");
  if (!token) return res.status(401).json( message: "Auth Error" );

  try 
    const decoded = jwt.verify(token, "randomString");
    req.user = decoded.user;
    next();
   catch (e) 
    console.error(e);
    res.status(500).send( message: "Invalid Token" );
  
;

这是我的 /routes/user.js

// Filename : user.js

const express = require("express");
const check, validationResult = require("express-validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const router = express.Router();
const auth = require("../middleware/auth");
const User = require("../model/User");



/**
 * @method - POST
 * @param - /signup
 * @description - User SignUp
 */

router.post(
    "/register",
    [
        check("username", "Please Enter a Valid Username")
        .not()
        .isEmpty(),
        check("email", "Please enter a valid email").isEmail(),
        check("password", "Please enter a valid password").isLength(
            min: 6
        )
    ],
    async (req, res) => 
        const errors = validationResult(req);
        if (!errors.isEmpty()) 
            return res.status(400).json(
                errors: errors.array()
            );
        

        const 
            username,
            email,
            password
         = req.body;
        try 
            let user = await User.findOne(
                email
            );
            if (user) 
                return res.status(400).json(
                    msg: "User Already Exists"
                );
            

            user = new User(
                username,
                email,
                password
            );

            const salt = await bcrypt.genSalt(10);
            user.password = await bcrypt.hash(password, salt);

            await user.save();

            const payload = 
                user: 
                    id: user.id
                
            ;

            jwt.sign(
                payload,
                "randomString", 
                    expiresIn: 10000
                ,
                (err, token) => 
                    if (err) throw err;
                    res.status(200).json(
                        token
                    );
                
            );
         catch (err) 
            console.log(err.message);
            res.status(500).send("Error in Saving");
        
    
);
router.post(
    "/login",
    [
      check("email", "Please enter a valid email").isEmail(),
      check("password", "Please enter a valid password").isLength(
        min: 6
      )
    ],
    async (req, res) => 
      const errors = validationResult(req);
  
      if (!errors.isEmpty()) 
        return res.status(400).json(
          errors: errors.array()
        );
      
  
      const  email, password  = req.body;
      try 
        let user = await User.findOne(
          email
        );
        if (!user)
          return res.status(400).json(
            message: "User Does Not Exist"
          );
  
        const isMatch = await bcrypt.compare(password, user.password);
        if (!isMatch)
          return res.status(400).json(
            message: "Incorrect Password!"
          );
  
        const payload = 
          user: 
            id: user.id
          
        ;
  
        jwt.sign(
          payload,
          "randomString",
          
            expiresIn: 3600
          ,
          (err, token) => 
            if (err) throw err;
            res.status(200).json(
              token
            );
          
        );
       catch (e) 
        console.error(e);
        res.status(500).json(
          message: "Server Error"
        );
      
    
  );

  /**
 * @method - POST
 * @description - Get LoggedIn User
 * @param - /user/me
 */

router.get("/profile", auth, async (req, res) => 

    try 
      // request.user is getting fetched from Middleware after token authentication
      const user = await User.findById(req.user.id);
      res.json(user);
     catch (e) 
      res.send( message: "Error in Fetching user" );
    
  );
module.exports = router;

【问题讨论】:

【参考方案1】:

在您的 Angular 应用中,您发送带有 authorization 标头的令牌

Authorization: token

但是在您的 API (auth.js) 中,您正在尝试访问 token 标头

req.header("token")

将您的 api 代码替换为

req.header("authorization")

【讨论】:

以上是关于angular + nodejs 控制台显示“GET http://localhost:4200/user/profile 401 (Unauthorized)”的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Mongoose、Express、Angular 4 和 NodeJS 上传/保存和显示图片

如何在 Angularjs 中调用 Nodejs 方法

Mysql 表数据未显示在使用 Nodejs 的 Angular 材料表上

从 mongoDB 获取数据并使用 Angular 和 NodeJs 在屏幕上打印

Nodejs,Express + Angular POST 404

刷新页面显示找不到文件错误如何使用 [angular js + NodeJS/ExpressJS] 解决