晚上好🌙🌙🌙
本答案参考通义千问
你提到的“飞度在线网络购物平台”是一个完整的项目,现在只差登录功能。这个功能涉及多个平台(扫码、手机验证码、微信/支付宝绑定等)的多端登录,并且要统一使用 Cookie 作为认证方式,后端使用 Node.js + Express + MySQL。
下面我将从 前端(UniApp) 和 后端(Node.js + Express + MySQL) 两个层面详细讲解如何实现 多端登录系统,包括:
✅ 一、整体思路与架构
1. 登录方式分类
- 扫码登录:通过二维码生成并扫码,用户授权后登录。
- 手机号+验证码登录:模拟短信验证码(假号码),用于手机端登录。
- 第三方绑定登录(微信、支付宝):用户绑定手机号后,可使用第三方账号登录。
2. 技术选型
- 前端(UniApp):支持多端(H5、小程序、App)。
- 后端(Node.js + Express):处理登录逻辑、验证、绑定、生成 Cookie。
- 数据库(MySQL):存储用户信息、绑定关系、登录记录等。
3. 登录机制
- 使用 Cookie 作为会话凭证,不使用 JWT(但可以兼容)。
- 用户登录成功后,后端生成一个
session_id 并写入 Cookie。 - 后端使用 Session 存储用户状态(如 Redis 或数据库中维护 session 表)。
✅ 二、数据库设计(MySQL)
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL, -- 手机号或邮箱
password VARCHAR(255), -- 加密后的密码(仅用于手机号登录)
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 第三方绑定表
CREATE TABLE third_party_bindings (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
platform ENUM('wechat', 'alipay') NOT NULL,
open_id VARCHAR(255) NOT NULL,
bind_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 登录日志表(可选)
CREATE TABLE login_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
login_type ENUM('qr', 'phone', 'wechat', 'alipay'),
ip VARCHAR(45),
login_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
✅ 三、后端实现(Node.js + Express)
1. 安装依赖
npm install express mysql2 cookie-parser session express-session
2. 基础配置(app.js / server.js)
const express = require('express');
const app = express();
const mysql = require('mysql2/promise');
const cookieParser = require('cookie-parser');
const session = require('express-session');
// 数据库连接
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'yourpassword',
database: 'flying_platform',
connectionLimit: 10
});
// Session 配置
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 1000 * 60 * 60 } // 1小时
}));
app.use(cookieParser());
app.use(express.json());
3. 登录接口(以手机号验证码为例)
3.1 发送验证码(模拟)
app.post('/api/send-verify-code', async (req, res) => {
const { phone } = req.body;
// 模拟发送验证码(实际应调用短信服务)
const code = Math.floor(100000 + Math.random() * 900000).toString();
// 存入 session 或缓存中(此处简化为直接返回)
res.cookie('verify_code', code, { maxAge: 60000 }); // 1分钟有效
res.json({ success: true, message: '验证码已发送' });
});
3.2 手机号+验证码登录
app.post('/api/login-phone', async (req, res) => {
const { phone, code } = req.body;
// 检查验证码是否匹配(此处简单比对)
const storedCode = req.cookies.verify_code;
if (code !== storedCode) {
return res.status(400).json({ error: '验证码错误' });
}
// 查询用户是否存在
const [rows] = await pool.query('SELECT * FROM users WHERE username = ?', [phone]);
if (rows.length === 0) {
return res.status(404).json({ error: '用户不存在' });
}
const user = rows[0];
// 设置 session
req.session.user = { id: user.id, username: user.username };
res.clearCookie('verify_code'); // 清除验证码 Cookie
res.json({ success: true, user: { id: user.id, username: user.username } });
});
4. 微信扫码登录(伪代码)
4.1 生成二维码
app.get('/api/qrcode', (req, res) => {
const qrCodeUrl = `https://api.weixin.qq.com/wxa/getwxacode?access_token=xxx`;
res.json({ qrcode_url: qrCodeUrl });
});
4.2 扫码后回调
app.get('/api/wechat-login', async (req, res) => {
const { code } = req.query;
// 调用微信接口获取 openId
const wxResponse = await fetch(`https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=${code}&grant_type=authorization_code`);
const data = await wxResponse.json();
if (!data.openid) {
return res.status(400).json({ error: '微信登录失败' });
}
// 查询是否有绑定手机号
const [bindingRows] = await pool.query('SELECT * FROM third_party_bindings WHERE platform = "wechat" AND open_id = ?', [data.openid]);
if (bindingRows.length > 0) {
// 已绑定,直接登录
const [userRows] = await pool.query('SELECT * FROM users WHERE id = ?', [bindingRows[0].user_id]);
req.session.user = userRows[0];
res.json({ success: true, user: userRows[0] });
} else {
// 未绑定,需要绑定手机号
res.json({ need_bind: true });
}
});
5. 绑定手机号接口
app.post('/api/bind-phone', async (req, res) => {
const { phone, code } = req.body;
const userId = req.session.user.id;
// 验证手机号和验证码
const storedCode = req.cookies.verify_code;
if (code !== storedCode) {
return res.status(400).json({ error: '验证码错误' });
}
// 更新用户手机号
await pool.query('UPDATE users SET username = ? WHERE id = ?', [phone, userId]);
// 绑定微信
await pool.query('INSERT INTO third_party_bindings (user_id, platform, open_id) VALUES (?, ?, ?)',
[userId, 'wechat', data.openid]);
res.json({ success: true });
});
✅ 四、前端(UniApp)实现
1. 扫码登录页面(uni-app 页面结构)
<template>
<view>
<image :src="qrcodeUrl" mode="aspectFit" />
<button @click="scanQr">扫码登录</button>
</view>
</template>
<script>
export default {
data() {
return {
qrcodeUrl: ''
};
},
mounted() {
this.generateQr();
},
methods: {
async generateQr() {
const res = await uni.request({
url: 'http://your-backend-domain/api/qrcode'
});
this.qrcodeUrl = res.data.qrcode_url;
},
scanQr() {
uni.scanCode({
success: (res) => {
uni.navigateTo({
url: '/pages/login/wechat-login?code=' + res.result
});
}
});
}
}
};
</script>
2. 手机号登录页面
<template>
<view>
<input v-model="phone" placeholder="手机号" />
<input v-model="code" placeholder="验证码" />
<button @click="sendVerifyCode">获取验证码</button>
<button @click="loginWithPhone">登录</button>
</view>
</template>
<script>
export default {
data() {
return {
phone: '',
code: ''
};
},
methods: {
async sendVerifyCode() {
await uni.request({
url: 'http://your-backend-domain/api/send-verify-code',
method: 'POST',
data: { phone: this.phone }
});
},
async loginWithPhone() {
const res = await uni.request({
url: 'http://your-backend-domain/api/login-phone',
method: 'POST',
data: { phone: this.phone, code: this.code }
});
if (res.data.success) {
uni.showToast({ title: '登录成功' });
uni.reLaunch({ url: '/pages/index/index' });
}
}
}
};
</script>
✅ 五、总结:多端登录流程图
[扫码] -> 生成二维码 -> 扫码 -> 获取 openId -> 判断是否绑定 -> 绑定手机号 -> 登录成功
[手机登录] -> 输入手机号 -> 获取验证码 -> 输入验证码 -> 登录成功
[微信/支付宝绑定] -> 扫码/跳转 -> 获取 openId -> 绑定手机号 -> 登录成功
✅ 六、注意事项
- 安全性:验证码需限制频率,防止暴力破解。
- Session 管理:建议使用 Redis 缓存 Session,提高性能。
- 跨域问题:前后端分离时注意设置 CORS。
- Cookie 作用域:确保 Cookie 在所有子域名下可用(如
.example.com)。
✅ 七、扩展建议(面试加分项)
- 可以加入 JWT 支持,实现无状态登录。
- 使用 Redis 优化 Session 性能。
- 实现 登录失效检测(如超时自动退出)。
- 添加 登录设备管理(查看最近登录设备)。
如果你希望我帮你把以上代码整合成一个完整项目结构,也可以告诉我,我可以提供更详细的文件结构和目录组织方案。