文字游戏
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

8.8 KiB

后端 API 实现参考

这是一个使用 Node.js + Express 的简单后端示例,展示如何实现登录接口。

快速开始 (Node.js + Express)

1. 初始化项目

mkdir admin-backend
cd admin-backend
npm init -y
npm install express cors jsonwebtoken bcryptjs dotenv
npm install -D nodemon typescript ts-node

2. 创建 server.js

const express = require('express')
const cors = require('cors')
const jwt = require('jsonwebtoken')
require('dotenv').config()

const app = express()
const PORT = process.env.PORT || 3000
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key'

// 中间件
app.use(cors())
app.use(express.json())

// 模拟用户数据
const users = [
  {
    id: '1',
    username: 'admin',
    password: '123456', // 实际应该加密存储
    email: 'admin@example.com',
    role: 'admin'
  },
  {
    id: '2',
    username: 'user',
    password: '123456',
    email: 'user@example.com',
    role: 'user'
  }
]

// 登录接口
app.post('/api/auth/login', (req, res) => {
  const { username, password } = req.body

  // 验证输入
  if (!username || !password) {
    return res.status(400).json({
      code: 400,
      message: '用户名和密码不能为空'
    })
  }

  // 查找用户
  const user = users.find(u => u.username === username && u.password === password)

  if (!user) {
    return res.status(401).json({
      code: 401,
      message: '用户名或密码错误'
    })
  }

  // 生成 JWT token
  const token = jwt.sign(
    { id: user.id, username: user.username, role: user.role },
    JWT_SECRET,
    { expiresIn: '7d' }
  )

  // 返回成功响应
  res.json({
    code: 200,
    message: '登录成功',
    data: {
      token,
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        role: user.role
      }
    }
  })
})

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

// 获取用户信息接口 (需要认证)
app.get('/api/auth/userinfo', authenticateToken, (req, res) => {
  const user = users.find(u => u.id === req.user.id)
  
  if (!user) {
    return res.status(404).json({
      code: 404,
      message: '用户不存在'
    })
  }

  res.json({
    code: 200,
    message: '获取成功',
    data: {
      id: user.id,
      username: user.username,
      email: user.email,
      role: user.role
    }
  })
})

// Token 验证中间件
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization']
  const token = authHeader && authHeader.split(' ')[1] // Bearer <token>

  if (!token) {
    return res.status(401).json({
      code: 401,
      message: 'Token 缺失'
    })
  }

  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(401).json({
        code: 401,
        message: 'Token 无效或已过期'
      })
    }
    req.user = user
    next()
  })
}

// 启动服务器
app.listen(PORT, () => {
  console.log(\`✅ 服务器运行在 http://localhost:\${PORT}\`)
  console.log(\`📝 API 文档: http://localhost:\${PORT}/api/docs\`)
})

3. 创建 .env

PORT=3000
JWT_SECRET=your-super-secret-key-change-in-production
NODE_ENV=development

4. 运行服务器

node server.js
# 或使用 nodemon 自动重启
npx nodemon server.js

API 端点说明

登录接口

请求

POST /api/auth/login
Content-Type: application/json

{
  "username": "admin",
  "password": "123456"
}

成功响应 (200)

{
  "code": 200,
  "message": "登录成功",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": "1",
      "username": "admin",
      "email": "admin@example.com",
      "role": "admin"
    }
  }
}

错误响应 (401)

{
  "code": 401,
  "message": "用户名或密码错误"
}

获取用户信息接口

请求

GET /api/auth/userinfo
Authorization: Bearer <token>

成功响应

{
  "code": 200,
  "message": "获取成功",
  "data": {
    "id": "1",
    "username": "admin",
    "email": "admin@example.com",
    "role": "admin"
  }
}

使用 cURL 测试

# 登录
curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"123456"}'

# 获取用户信息
curl -X GET http://localhost:3000/api/auth/userinfo \
  -H "Authorization: Bearer YOUR_TOKEN_HERE"

使用 Postman 测试

  1. 打开 Postman
  2. 创建 POST 请求到 http://localhost:3000/api/auth/login
  3. 在 Body → raw → JSON 中输入:
    {
      "username": "admin",
      "password": "123456"
    }
    
  4. 点击 Send
  5. 复制响应中的 token

Python Flask 示例

from flask import Flask, request, jsonify
from flask_cors import CORS
from functools import wraps
import jwt
from datetime import datetime, timedelta

app = Flask(__name__)
CORS(app)
app.config['JSON_AS_ASCII'] = False
SECRET_KEY = 'your-secret-key'

# 模拟用户数据
USERS = [
    {'id': '1', 'username': 'admin', 'password': '123456', 'email': 'admin@example.com', 'role': 'admin'},
    {'id': '2', 'username': 'user', 'password': '123456', 'email': 'user@example.com', 'role': 'user'}
]

def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('Authorization', '').replace('Bearer ', '')
        if not token:
            return jsonify({'code': 401, 'message': 'Token 缺失'}), 401
        try:
            data = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
            request.user_id = data['id']
        except:
            return jsonify({'code': 401, 'message': 'Token 无效'}), 401
        return f(*args, **kwargs)
    return decorated

@app.route('/api/auth/login', methods=['POST'])
def login():
    data = request.json
    username = data.get('username')
    password = data.get('password')
    
    if not username or not password:
        return jsonify({'code': 400, 'message': '用户名和密码不能为空'}), 400
    
    user = next((u for u in USERS if u['username'] == username and u['password'] == password), None)
    
    if not user:
        return jsonify({'code': 401, 'message': '用户名或密码错误'}), 401
    
    token = jwt.encode(
        {'id': user['id'], 'username': user['username']},
        SECRET_KEY,
        algorithm='HS256'
    )
    
    return jsonify({
        'code': 200,
        'message': '登录成功',
        'data': {
            'token': token,
            'user': {
                'id': user['id'],
                'username': user['username'],
                'email': user['email'],
                'role': user['role']
            }
        }
    })

@app.route('/api/auth/userinfo', methods=['GET'])
@token_required
def get_userinfo():
    user = next((u for u in USERS if u['id'] == request.user_id), None)
    if not user:
        return jsonify({'code': 404, 'message': '用户不存在'}), 404
    
    return jsonify({
        'code': 200,
        'message': '获取成功',
        'data': {
            'id': user['id'],
            'username': user['username'],
            'email': user['email'],
            'role': user['role']
        }
    })

if __name__ == '__main__':
    app.run(debug=True, port=3000)

Java Spring Boot 示例

@RestController
@RequestMapping("/api/auth")
@CrossOrigin(origins = "*")
public class AuthController {
    
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest request) {
        // 验证用户
        User user = authenticateUser(request.getUsername(), request.getPassword());
        
        if (user == null) {
            return ResponseEntity.status(401).body(new ApiResponse(401, "用户名或密码错误"));
        }
        
        // 生成 JWT token
        String token = JwtUtils.generateToken(user);
        
        return ResponseEntity.ok(new ApiResponse(200, "登录成功", 
            new LoginResponse(token, user)));
    }
    
    @GetMapping("/userinfo")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity<?> getUserInfo() {
        User user = getCurrentUser();
        return ResponseEntity.ok(new ApiResponse(200, "获取成功", user));
    }
}

注意事项

  1. 密码加密:在生产环境中,必须加密存储密码(使用 bcrypt 等)
  2. HTTPS:生产环境必须使用 HTTPS
  3. CORS:根据前端域名配置 CORS
  4. Token 有效期:建议设置合理的过期时间(如 7 天)
  5. 错误处理:返回统一的错误格式
  6. 日志记录:记录所有登录尝试
  7. 速率限制:防止暴力破解

与前端集成

  1. 启动后端服务:node server.js
  2. 启动前端开发服务:npm run dev
  3. 前端会自动从 http://localhost:3000/api 调用后端接口
  4. 在登录页输入 admin / 123456 进行测试