first commit

This commit is contained in:
编码猿
2024-09-27 01:09:14 +08:00
commit 9420feb4c9
56 changed files with 1811 additions and 0 deletions

1
NodeServer/routes/.pydio Normal file
View File

@@ -0,0 +1 @@
3fa0f904-8283-42e5-bf5b-a1b1c84cadc7

129
NodeServer/routes/index.js Normal file
View File

@@ -0,0 +1,129 @@
const express = require('express');
const router = express.Router();
const sql = require("../mysql");
const redis = require("../redis");
const BroadcastChannel = require("../BroadcastChannel");
/**
* 用户已扫码但是未确认这个接口只是为了通知web端用户当前的进展状态
*/
router.get('/SweepStatus', async (req, res, next) => {
let uuid = req.query.uuid;
BroadcastChannel.SweepStatus.postMessage(uuid);
res.json({ status: 200, msg: '发送成功', data: null })
});
/**
* 移动端App确认登录按钮点击时候的ajax处理
*/
router.get('/login', async (req, res, next) => {
let uuid = req.query.uuid; // uuid
let uid = req.query.uid; // 用户id
let RedisUid = await redis.get(uuid);
if (RedisUid == null || RedisUid == undefined) {
res.json({
status: 404,
msg: '二维码失效或不存在',
data: null
});
} else {
if (RedisUid.length !== 0) {
res.json({
status: 404,
msg: '已登录,请勿重复扫码',
data: null
});
} else {
// 查询用户信息
let user = (await sql.query({ sql: 'select * from user where id = ?', data: [ uid ] }))[0];
// 保存用户数据到对应key的redis中
redis.set(uuid, JSON.stringify(user));
res.json({
status: 200,
msg: '扫码成功',
data: null
});
}
}
});
/**
* TODO
* 被移动端App轮询的接口主要让移动端知道我移动端现在已登录的用户所对
* 应的web端是否在请求让我授权登录如果在web端在请求登录那么移动端自
* 动进入授权页面让用户授权,授权后结束轮询,否则一直轮询
* PS: uniapp 无法连接到 Node.js 的 socket.io所以只能用很low而且
* 很消耗移动端资源的轮询了。等解决这个问题自然用socket重写这里实现
*/
router.get('/InquiryWebIsLogining', async (req, res, next) => {
let uid = req.query.uid; // 用户id
// console.log("uid: ", uid);
let UserId = await redis.get(uid);
// 没有查询到redis的 uid 数据的话
if (UserId == null || UserId == undefined) {
res.json({
status: 404,
msg: '没有对应的web端请求登录',
data: null
});
} else {
// UserId 有数值但是为空表示web请求登录但移动端未授权
if (UserId.length == 0) {
res.json({
status: 200,
msg: 'web端正在请求授权',
data: null
});
// UserId 有数值但是不为空表示web请求登录移动端已授权并且redis未超时
} else {
res.json({
status: 500,
msg: '授权成功,请勿重复授权',
data: null
})
}
}
});
/**
* 授权web端登录的接口主要被移动端App调用拿到移动端给的用户id
* 然后从数据库获取用户的详细数据通过广播把用户数据通知给web端
*/
router.get('/AuthorizedWeb', async (req, res, next) => {
let uid = req.query.uid; // 用户id
let UserId = await redis.get(uid);
if (UserId == null || UserId == undefined) {
res.json({
status: 404,
msg: '没有对应的web端请求登录',
data: null
});
} else {
// UserId 有数值,但是为空
if (UserId.length == 0) {
// 查询用户信息
let user = (await sql.query({ sql: 'select * from user where id = ?', data: [ uid ] }))[0];
// 保存用户数据到对应key的redis中
redis.set(uid, JSON.stringify(user));
BroadcastChannel.AuthorizedWeb.postMessage(user);
res.json({
status: 200,
msg: '成功授权',
data: null
});
// UserId 有数值但是不为空表示web请求登录移动端已授权并且redis未超时
} else {
res.json({
status: 404,
msg: '授权成功,请勿重复授权',
data: null
})
}
}
});
module.exports = router;

View File

@@ -0,0 +1,68 @@
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const utils = require('../utils');
const redis = require('../redis');
const BroadcastChannel = require("../BroadcastChannel");
io.on('connection', (socket) => {
// Web端获取二维码和uuid
socket.on('getQRcode', () => {
let uuid = utils.randomNumber(); // 生成uuid
let QRcode = utils.getQRcode(uuid); // 根据uuid生成二维码的base64
redis.set(uuid, ''); // 保存uuid 到redis中但是用户数据留空由移动端上传
socket.emit('sendQRcode', { uuid: uuid, QRcode: QRcode }); // 向web端发送uuid和二维码base64数据
});
/**
* 检查移动端用户是否扫码二维码登录,如果扫码登录了
* 那么二维码显示登录成功样式,并显示登录用户信息
*/
socket.on('checkScanCode', async key => {
console.log(`Web端(Vue)在询问用户是否扫码:${key}...`);
let userInfo = await redis.get(key);
// 如果key对应的value为空那么用户未扫码
// 反之 用户扫码并确定登录
userInfo == null || userInfo.length == 0 ? socket.emit("waitScanCode") : socket.emit("SuccessScanCode", userInfo);
});
/**
* 场景用户已经移动端App扫码登录后本地保存有用户的id
* 功能模仿微信web端发送请求然后移动端授权web端的本次登录
* web端请求移动端授权登录
*/
socket.on('WebRequestLogin', async id => {
console.log("web端请求登录用户的id: ", id);
let WebId = await redis.get(id);
// 如果redis中没有数值表示web端还未开始请求移动端授权登录那么保存id为redis key
// 如果redis中有数值表示web端用户已经在请求移动端授权登录那么不重复保存id并且提示web端
if (WebId == null) {
redis.set(id, ''); // 使用web端的用户id作为redis的key存储起来value对应的数值由移动端填充
} else {
console.log("不等于null")
socket.emit("DoNotRepeatRequest", '已发送登录请求,请在移动端授权本次登录')
}
});
// 接受redis key超时的广播通知也就是用户长时间未扫二维码主要在redis/index.js中进行订阅key失效的事件
// 然后广播通知被这里代码onmessage到然后 socket 通知 Vue 前端
BroadcastChannel.SubscribeExpired.onmessage = event => socket.emit("ScanCodeOvertime");
// 用户已扫码,但是未确认
BroadcastChannel.SweepStatus.onmessage = event => socket.emit("ScanCodeing", event.data);
// 移动端成功授权web端
BroadcastChannel.AuthorizedWeb.onmessage = function(event) {
console.log("event: ", event);
socket.emit("AuthorizedWebSuccess", event);
};
socket.on('disconnect', () => console.log('web端用户掉线...'));
});
http.listen(9080, () => console.log('socket listening on *: 9080'));