导航
持久登录允许用户即使在关闭浏览器后重新访问应用时也保持登录状态。为实现这一功能,我们将使用 Token (例如 JWT) 存储会话信息,并通过 HTTP-Only Cookie 保护 Token,以防止客户端 JavaScript 访问。

JWT,将 JWT 存储在 HTTP-Only Cookie 中,以便浏览器自动在后续请求中发送。Cookie 持久化 Token,自动在后续请求中验证用户是否已登录。JWT 中找到用户会话信息,并更新应用状态。<template>
  <div>
    <h2>Login</h2>
    <form @submit.prevent="login">
      <input v-model="username" placeholder="Username" required />
      <input v-model="password" placeholder="Password" type="password" required />
      <button type="submit">Login</button>
    </form>
    <p v-if="error">{{ error }}</p>
  </div>
</template>
<script>
import axios from 'axios';
export default {
  data() {
    return {
      username: '',
      password: '',
      error: null,
    };
  },
  methods: {
    async login() {
      try {
        const res = await axios.post('/api/login', {
          username: this.username,
          password: this.password,
        }, { withCredentials: true });
        
        if (res.data.success) {
          this.$router.push('/home');
        }
      } catch (err) {
        this.error = 'Login failed. Please check your credentials.';
      }
    },
  },
};
</script>
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const router = express.Router();
const SECRET_KEY = 'your_jwt_secret_key';  // 换成更安全的密钥
const COOKIE_NAME = 'auth_token';
router.post('/login', async (req, res) => {
    const { username, password } = req.body;
    // 假设此用户从数据库查询
    const user = { id: 1, username: 'test', passwordHash: await bcrypt.hash('password', 10) };
    if (user && await bcrypt.compare(password, user.passwordHash)) {
        const token = jwt.sign({ id: user.id, username: user.username }, SECRET_KEY, { expiresIn: '7d' });
        res.cookie(COOKIE_NAME, token, {
            httpOnly: true,
            secure: process.env.NODE_ENV === 'production',
            maxAge: 7 * 24 * 60 * 60 * 1000,  // 7 days
        });
        return res.json({ success: true, message: 'Login successful' });
    }
    return res.status(401).json({ success: false, message: 'Invalid credentials' });
});
module.exports = router;
const jwt = require('jsonwebtoken');
const SECRET_KEY = 'your_jwt_secret_key';
const COOKIE_NAME = 'auth_token';
module.exports = (req, res, next) => {
    const token = req.cookies[COOKIE_NAME];
    
    if (token) {
        try {
            const user = jwt.verify(token, SECRET_KEY);
            req.user = user;
            next();
        } catch (err) {
            res.clearCookie(COOKIE_NAME);
            return res.status(401).json({ success: false, message: 'Token expired' });
        }
    } else {
        return res.status(401).json({ success: false, message: 'Unauthorized' });
    }
};
在 Express.js 中使用此中间件保护路由:
const express = require('express');
const authMiddleware = require('./authMiddleware');
const app = express();
app.use('/api/protected', authMiddleware, (req, res) => {
    res.json({ success: true, message: `Hello ${req.user.username}, you are authorized.` });
});
在不同源的一个系统下,任意一个站点一个程序做了登录操作,其他站点或者程序同样处于登录状态的这种机制叫做单点登录机制。
