You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular(v5)中从Node/Express获取JWT存入LocalStorage并跳转至Profile路由

实现步骤:从Node/Express获取JWT并在Angular中处理

我来帮你一步步完成这个需求,分后端(Node/Express)和前端(Angular)两部分梳理:


一、后端(Node/Express)配置

首先要确保你的登录接口能正确生成并返回JWT,这里以routes/auth.js为例:

1. 安装依赖

先确保你装了生成JWT和加密密码的依赖:

npm install jsonwebtoken bcryptjs cors

2. 编写登录接口

在routes/auth.js中添加登录逻辑,验证用户后生成JWT返回:

const express = require('express');
const router = express.Router();
const User = require('../models/schema');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
// 假设你在config目录下有config.js,存储JWT密钥
const config = require('../config/config');

// 登录接口
router.post('/login', async (req, res) => {
  try {
    const { email, password } = req.body;
    
    // 查找用户
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(400).json({ msg: '用户不存在' });
    }

    // 验证密码(假设你存储的是加密后的密码)
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(400).json({ msg: '密码错误' });
    }

    // 生成JWT
    const tokenPayload = {
      id: user._id,
      name: user.name,
      email: user.email
    };

    jwt.sign(
      tokenPayload,
      config.JWT_SECRET, // 你的JWT密钥,要存在环境变量里更安全
      { expiresIn: '7d' }, // 设置token过期时间,比如7天
      (err, token) => {
        if (err) throw err;
        res.json({
          token,
          user: {
            id: user._id,
            name: user.name,
            email: user.email
          }
        });
      }
    );
  } catch (err) {
    console.error(err.message);
    res.status(500).json({ msg: '服务器内部错误' });
  }
});

module.exports = router;

3. 挂载路由并配置CORS

在根目录的index.js中挂载路由,并解决跨域问题:

const express = require('express');
const app = express();
const authRoutes = require('./routes/auth');
const cors = require('cors');

// 配置CORS,允许前端跨域请求
app.use(cors());
// 解析JSON请求体
app.use(express.json());

// 挂载认证路由
app.use('/api/auth', authRoutes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`服务器运行在端口${PORT}`));

二、前端(Angular)配置

接下来处理Angular部分,实现登录请求、存储JWT、跳转Profile路由的逻辑:

1. 创建Auth服务

在services目录下新建auth.service.ts,封装登录、token存储和路由跳转逻辑:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private apiBaseUrl = 'http://localhost:3000/api/auth'; // 你的后端API地址

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

  // 发送登录请求
  login(email: string, password: string): Observable<any> {
    return this.http.post(`${this.apiBaseUrl}/login`, { email, password });
  }

  // 把JWT存储到LocalStorage
  saveToken(token: string): void {
    localStorage.setItem('jwt_token', token);
  }

  // 存储当前用户信息到LocalStorage
  saveUser(user: any): void {
    localStorage.setItem('current_user', JSON.stringify(user));
  }

  // 获取LocalStorage中的token
  getToken(): string | null {
    return localStorage.getItem('jwt_token');
  }

  // 登出逻辑
  logout(): void {
    localStorage.removeItem('jwt_token');
    localStorage.removeItem('current_user');
    this.router.navigate(['/login']);
  }
}

2. 改造Login组件

在login.component.ts中处理表单提交,调用Auth服务完成登录:

import { Component } from '@angular/core';
import { AuthService } from '../../services/auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent {
  email: string = '';
  password: string = '';
  errorMessage: string = '';

  constructor(private authService: AuthService) { }

  onLoginSubmit(): void {
    this.authService.login(this.email, this.password).subscribe({
      next: (response) => {
        // 存储token和用户信息
        this.authService.saveToken(response.token);
        this.authService.saveUser(response.user);
        // 跳转至Profile路由
        this.authService.router.navigate(['/profile']);
      },
      error: (err) => {
        this.errorMessage = err.error.msg || '登录失败,请检查账号密码';
        console.error(err);
      }
    });
  }
}

对应的login.component.html示例:

<div class="login-form">
  <h2>用户登录</h2>
  <form (ngSubmit)="onLoginSubmit()">
    <div class="form-group">
      <label>邮箱</label>
      <input type="email" [(ngModel)]="email" name="email" required>
    </div>
    <div class="form-group">
      <label>密码</label>
      <input type="password" [(ngModel)]="password" name="password" required>
    </div>
    <button type="submit" class="login-btn">登录</button>
    <p *ngIf="errorMessage" class="error-text">{{ errorMessage }}</p>
  </form>
</div>

3. 配置Profile路由与守卫

为了确保只有登录用户能访问Profile页面,添加路由守卫:

(1)创建AuthGuard

在services目录下新建auth.guard.ts:

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) { }

  canActivate(): boolean {
    if (this.authService.getToken()) {
      return true; // 有token,允许访问
    } else {
      this.router.navigate(['/login']); // 无token,跳转登录页
      return false;
    }
  }
}

(2)配置路由

在app.module.ts中更新路由配置:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';
import { LoginComponent } from './components/login/login.component';
import { ProfileComponent } from './components/profile/profile.component';
import { HomeComponent } from './components/home/home.component';
import { AuthGuard } from './services/auth.guard';

const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'login', component: LoginComponent },
  // 用AuthGuard保护Profile路由
  { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
  { path: '**', redirectTo: '' }
];

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    ProfileComponent,
    HomeComponent
    // 其他组件
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot(appRoutes)
  ],
  providers: [AuthGuard],
  bootstrap: [AppComponent]
})
export class AppModule { }

4. 改造Profile组件

在profile.component.ts中获取用户信息并展示:

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
  currentUser: any;

  constructor(public authService: AuthService) { }

  ngOnInit(): void {
    // 从LocalStorage获取用户信息
    const userStr = localStorage.getItem('current_user');
    this.currentUser = userStr ? JSON.parse(userStr) : null;
  }
}

对应的profile.component.html示例:

<div class="profile-card">
  <h2>个人资料</h2>
  <div class="info-item">
    <span>姓名:</span>{{ currentUser.name }}
  </div>
  <div class="info-item">
    <span>邮箱:</span>{{ currentUser.email }}
  </div>
  <div class="info-item">
    <span>用户ID:</span>{{ currentUser.id }}
  </div>
  <button (click)="authService.logout()" class="logout-btn">登出</button>
</div>

内容的提问来源于stack exchange,提问作者Manish Vashisth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:51:03