登录接口思路和开发

输入用户名和密码,返回token。这个token最好存储在redis中,设置过期时间2小时,过期后就不能使用。或者存储在数据库中。

只要是没有过期的token都可以作为调用接口的凭证。所以多个用户登录就有多个token返回。

调用接口的方式:

将token放在header中。

比如:

复制代码
// 以微信小程序 wx.request 为例[citation:5]
wx.request({
  url: 'https://api.example.com/data',
  method: 'POST',
  header: { // 此处设置请求头参数
    'Content-Type': 'application/json', // 告诉服务器发送的是JSON数据
    'Authorization': 'Bearer your_token_here', // 传递身份令牌
    'X-Custom-Header': 'CustomValue' // 传递任何自定义业务参数
  },
  data: { // 请求体数据,与header是独立的
    key1: 'value1',
    key2: 'value2'
  },
  success(res) {
    console.log(res.data);
  }
})

接口接收token:

复制代码
const express = require('express');
const app = express();
const PORT = 3000;

// 中间件:解析JSON请求体
app.use(express.json());

// 模拟用户数据库(实际项目中应使用数据库)
const mockUsers = [
  { id: 1, username: 'user1', role: 'admin' },
  { id: 2, username: 'user2', role: 'user' }
];

// 模拟令牌存储(实际项目中应使用Redis等)
const validTokens = new Map();

// 生成模拟令牌(实际项目中应使用JWT等)
function generateToken(userId) {
  const token = `token_${userId}_${Date.now()}`;
  validTokens.set(token, { 
    userId, 
    expiresAt: Date.now() + 3600000 // 1小时后过期
  });
  return token;
}

// 中间件:验证Bearer Token
function verifyToken(req, res, next) {
  // 1. 从Authorization头获取令牌
  const authHeader = req.headers['authorization'];
  
  if (!authHeader) {
    return res.status(401).json({
      code: 401,
      message: '未提供认证令牌',
      error: 'Missing Authorization header'
    });
  }
  
  // 2. 检查是否为Bearer Token
  const parts = authHeader.split(' ');
  if (parts.length !== 2 || parts[0] !== 'Bearer') {
    return res.status(401).json({
      code: 401,
      message: '令牌格式错误,应为 "Bearer <token>"',
      error: 'Invalid token format'
    });
  }
  
  const token = parts[1];
  
  // 3. 验证令牌有效性
  const tokenData = validTokens.get(token);
  
  if (!tokenData) {
    return res.status(401).json({
      code: 401,
      message: '令牌无效或已过期',
      error: 'Invalid token'
    });
  }
  
  // 4. 检查令牌是否过期
  if (Date.now() > tokenData.expiresAt) {
    validTokens.delete(token); // 清理过期令牌
    return res.status(401).json({
      code: 401,
      message: '令牌已过期',
      error: 'Token expired'
    });
  }
  
  // 5. 查找对应用户信息
  const user = mockUsers.find(u => u.id === tokenData.userId);
  if (!user) {
    return res.status(401).json({
      code: 401,
      message: '用户不存在',
      error: 'User not found'
    });
  }
  
  // 6. 将用户信息附加到请求对象,供后续中间件/路由使用
  req.user = user;
  req.token = token;
  
  // 令牌验证通过,继续下一个中间件/路由
  next();
}

// ==================== 接口路由 ====================

// 1. 登录接口(获取Token)
app.post('/api/auth/login', (req, res) => {
  const { username, password } = req.body;
  
  // 模拟用户验证(实际项目中应验证密码哈希)
  const user = mockUsers.find(u => u.username === username);
  
  if (!user) {
    return res.status(401).json({
      code: 401,
      message: '用户名或密码错误',
      error: 'Invalid credentials'
    });
  }
  
  // 生成令牌
  const token = generateToken(user.id);
  
  res.json({
    code: 200,
    message: '登录成功',
    data: {
      token,
      user: {
        id: user.id,
        username: user.username,
        role: user.role
      },
      expiresIn: 3600 // 令牌有效时间(秒)
    }
  });
});

// 2. 需要Token验证的受保护接口
app.get('/api/user/profile', verifyToken, (req, res) => {
  // 通过verifyToken中间件后,req.user已包含用户信息
  res.json({
    code: 200,
    message: '获取用户信息成功',
    data: {
      user: req.user,
      timestamp: new Date().toISOString()
    }
  });
});

// 3. 需要Token验证的POST接口(接收小程序请求)
app.post('/api/data/submit', verifyToken, (req, res) => {
  const requestBody = req.body;
  const customHeader = req.headers['x-custom-header'];
  
  res.json({
    code: 200,
    message: '数据接收成功',
    data: {
      receivedData: requestBody,
      customHeader: customHeader,
      processedBy: req.user.username,
      serverTime: new Date().toISOString()
    }
  });
});

// 4. 令牌刷新接口
app.post('/api/auth/refresh', verifyToken, (req, res) => {
  const oldToken = req.token;
  const newToken = generateToken(req.user.id);
  
  // 使旧令牌失效
  validTokens.delete(oldToken);
  
  res.json({
    code: 200,
    message: '令牌刷新成功',
    data: {
      token: newToken,
      expiresIn: 3600
    }
  });
});

// 5. 登出接口
app.post('/api/auth/logout', verifyToken, (req, res) => {
  validTokens.delete(req.token);
  
  res.json({
    code: 200,
    message: '登出成功'
  });
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error('服务器错误:', err);
  res.status(500).json({
    code: 500,
    message: '服务器内部错误',
    error: process.env.NODE_ENV === 'development' ? err.message : undefined
  });
});

// 启动服务器
app.listen(PORT, () => {
  console.log(`✅ 服务器已
相关推荐
萌萌哒草头将军10 小时前
Node.js 存在多个严重安全漏洞!官方建议尽快升级🚀🚀🚀
vue.js·react.js·node.js
这个图像胖嘟嘟11 小时前
前端开发的基本运行环境配置
开发语言·javascript·vue.js·react.js·typescript·npm·node.js
前端付豪14 小时前
必知Node应用性能提升及API test 接口测试
前端·react.js·node.js
王同学 学出来14 小时前
vue+nodejs项目在服务器实现docker部署
服务器·前端·vue.js·docker·node.js
源猿人15 小时前
使用 Node.js 批量下载全国行政区 GeoJSON(含省级 + 地级市)
node.js
_Kayo_17 小时前
Node.JS 学习笔记7
笔记·学习·node.js
程序员爱钓鱼19 小时前
Node.js 编程实战:博客系统 —— 用户注册登录与文章管理
前端·后端·node.js
JaredYe20 小时前
用 Node.js 从旧版 PPT 中提取文本:轻量开源工具 ppt-to-text
node.js·powerpoint·ppt
TDengine (老段)20 小时前
TDengine Node.js 语言连接器入门指南
大数据·开发语言·物联网·node.js·vim·时序数据库·tdengine
余道各努力,千里自同风20 小时前
node.js 操作 MongoDB
数据库·mongodb·node.js