Skip to content

Commit

Permalink
Merge pull request #916 from pxgo/master
Browse files Browse the repository at this point in the history
优化
  • Loading branch information
pxgo authored Sep 6, 2023
2 parents d8c0f3a + 186ef7b commit 7208ba0
Show file tree
Hide file tree
Showing 14 changed files with 378 additions and 220 deletions.
1 change: 1 addition & 0 deletions dataModels/ExamsPaperModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ schema.statics.extendPapers = async (papers, options) => {
_id: paper._id,
tlm: paper.tlm,
toc: paper.toc,
type: paper.type,
passed: paper.passed,
timeOut: paper.timeOut,
submitted: paper.submitted,
Expand Down
265 changes: 142 additions & 123 deletions dataModels/VerificationModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,164 +4,179 @@ const baseInfoTimeout = 60 * 1000;
const secretTimeout = 2 * 60 * 1000;

const mongoose = require('../settings/database');
const schema = new mongoose.Schema({
_id: String,
// 验证的类型
type: {
type: String,
required: 1,
index: 1
},
// 获取验证的用户ID
uid: {
type: String,
default: '',
index: 1
},
// 获取验证的时间
toc: {
type: Date,
default: Date.now,
index: 1
},
ip: {
type: String,
default: '',
index: 1,
},
port: {
type: String,
default: '',
},
// 是否已经对比过原始数据
used: {
type: Boolean,
default: false,
index: 1
},
// 原始数据比对是否通过
passed: {
type: Boolean,
default: false,
index: 1
},
// 是否已经使用过验证通过后的加密串
secretUsed: {
type: Boolean,
default: false,
index: 1
},
// 加密串比对是否通过
secretPassed: {
type: Boolean,
default: false,
index: 1
const schema = new mongoose.Schema(
{
_id: String,
// 验证的类型
type: {
type: String,
required: 1,
index: 1,
},
// 获取验证的用户ID
uid: {
type: String,
default: '',
index: 1,
},
// 获取验证的时间
toc: {
type: Date,
default: Date.now,
index: 1,
},
ip: {
type: String,
default: '',
index: 1,
},
port: {
type: String,
default: '',
},
// 是否已经对比过原始数据
used: {
type: Boolean,
default: false,
index: 1,
},
// 原始数据比对是否通过
passed: {
type: Boolean,
default: false,
index: 1,
},
// 是否已经使用过验证通过后的加密串
secretUsed: {
type: Boolean,
default: false,
index: 1,
},
// 加密串比对是否通过
secretPassed: {
type: Boolean,
default: false,
index: 1,
},
// 加密串
secret: {
type: String,
index: 1,
default: '',
},
// 图形验证码数据
// 验证原始数据之后 会增加属性userAnswer,记录用户提交的答案
c: {
type: mongoose.Schema.Types.Mixed,
required: true,
},
},
// 加密串
secret: {
type: String,
index: 1,
default: ''
{
collection: 'verifications',
},
// 图形验证码数据
// 验证原始数据之后 会增加属性userAnswer,记录用户提交的答案
c: {
type: mongoose.Schema.Types.Mixed,
required: true,
}
}, {
collection: 'verifications'
});
);

/*
* 抛出验证失败的错误
* */
* 抛出验证失败的错误
* */
schema.statics.throwFailedError = async (message = '验证失败') => {
throwErr(400, message);
};

/*
* 验证原始信息通过后生成加密串
* */
* 验证原始信息通过后生成加密串
* */
schema.statics.newSecret = async () => {
const apiFunction = require('../nkcModules/apiFunction');
const secret = apiFunction.getRandomString('aA0', 64);
const VerificationModel = mongoose.model('verifications');
const v = await VerificationModel.countDocuments({secret});
if(v !== 0) {
const v = await VerificationModel.countDocuments({ secret });
if (v !== 0) {
return await VerificationModel.newSecret();
} else {
return secret;
}
};

/*
* 验证是否被使用过、或者是否超时
* */
schema.methods.verifyBaseInfo = async function() {
* 验证是否被使用过、或者是否超时
* */
schema.methods.verifyBaseInfo = async function () {
const VerificationModel = mongoose.model('verifications');
if(this.used) await VerificationModel.throwFailedError();
if (this.used) {
await VerificationModel.throwFailedError();
}
let errorStr;
if(Date.now() - this.toc > baseInfoTimeout) {
if (Date.now() - this.toc > baseInfoTimeout) {
errorStr = '验证失败';
}
await this.updateOne({used: true});
if(errorStr) await VerificationModel.throwFailedError();
await this.updateOne({ used: true });
if (errorStr) {
await VerificationModel.throwFailedError();
}
};


/*
* 随机获取验证数据
* @param {Object} options
* @param {String} uid 用户ID
* @param {String} ip
* @param {String} port
* @return {Object}
* @param {String} type 验证类型
* @param {Object} 验证类型对应的相关数据
* @author pengxiguaa 2020-9-24
* */
* 随机获取验证数据
* @param {Object} options
* @param {String} uid 用户ID
* @param {String} ip
* @param {String} port
* @return {Object}
* @param {String} type 验证类型
* @param {Object} 验证类型对应的相关数据
* @author pengxiguaa 2020-9-24
* */
schema.statics.getVerificationData = async (options) => {
const VerificationModel = mongoose.model('verifications');
await VerificationModel.verifyCountLimit(options);
const verifications = require('../nkcModules/verification');
const SettingModel = mongoose.model('settings');
const verificationSettings = await SettingModel.getSettings('verification');
const types = verificationSettings.enabledTypes;
if(types.length === 0) return {type: 'unEnabled'};
if (types.length === 0) {
return { type: 'unEnabled' };
}
const type = types[Math.round(Math.random() * (types.length - 1))];
const data = await verifications[type].create();
const {uid, ip, port} = options;
const { uid, ip, port } = options;
const verification = VerificationModel({
_id: SettingModel.newObjectId(),
type,
uid,
ip,
port,
c: data
c: data,
});
await verification.save();
delete data.answer;
data.type = type;
data._id = verification._id;
return data;
}
};

/*
* 验证原始数据
* */
* 验证原始数据
* */
schema.statics.verifyData = async (verificationData) => {
const VerificationModel = mongoose.model('verifications');
const verifications = require('../nkcModules/verification');
const {_id, type, uid, ip} = verificationData;
const { _id, type, uid, ip } = verificationData;
const verification = await VerificationModel.findOne({
_id, type, uid, ip
_id,
type,
uid,
ip,
});
if(!verification) await VerificationModel.throwFailedError();
if (!verification) {
await VerificationModel.throwFailedError();
}
await verification.verifyBaseInfo();
if(!verifications[verification.type].verify(verificationData, verification.c)) {
if (
!verifications[verification.type].verify(verificationData, verification.c)
) {
await verification.updateOne({
'c.userAnswer': verificationData.answer
'c.userAnswer': verificationData.answer,
});
await VerificationModel.throwFailedError();
}
Expand All @@ -170,58 +185,62 @@ schema.statics.verifyData = async (verificationData) => {
await verification.updateOne({
secret,
'c.userAnswer': verificationData.answer,
passed: true
passed: true,
});
return secret;
}

};

/*
* 验证加密串
* */
* 验证加密串
* */
schema.statics.verifySecret = async (options) => {
const VerificationModel = mongoose.model('verifications');
const {uid, ip, secret} = options;
if(secret === 'unEnabled') {
const { uid, ip, secret } = options;
if (secret === 'unEnabled') {
// 未开启验证
const SettingModel = mongoose.model('settings');
const verificationSettings = await SettingModel.getSettings('verification');
if(verificationSettings.enabledTypes.length !== 0) await VerificationModel.throwFailedError();
if (verificationSettings.enabledTypes.length !== 0) {
await VerificationModel.throwFailedError();
}
} else {
// 已开启验证
const verification = await VerificationModel.findOne({
uid, ip, secret
uid,
ip,
secret,
});
if(
if (
!verification ||
verification.secretUsed ||
(Date.now() - verification.toc) > secretTimeout
Date.now() - verification.toc > secretTimeout
) {
await verification.updateOne({secretUsed: true});
await verification.updateOne({ secretUsed: true });
await VerificationModel.throwFailedError();
} else {
await verification.updateOne({secretUsed: true, secretPassed: true});
await verification.updateOne({ secretUsed: true, secretPassed: true });
}
}
}
};

/*
* 次数限制检测
* */
* 次数限制检测
* */
schema.statics.verifyCountLimit = async (options) => {
const VerificationModel = mongoose.model('verifications');
const SettingModel = mongoose.model('settings');
const verificationSettings = await SettingModel.getSettings('verification');
const {time, count} = verificationSettings.countLimit;
const {ip} = options;
const { time, count } = verificationSettings.countLimit;
const { ip } = options;
const verificationCount = await VerificationModel.countDocuments({
ip,
toc: {
$gte: Date.now() - time * 60 * 1000
}
$gte: Date.now() - time * 60 * 1000,
},
});
if(verificationCount >= count) throwErr(403, `获取图形验证码频率过快,请稍后再试`);
if (verificationCount >= count) {
throwErr(403, `获取图形验证码频率过快,请稍后再试`);
}
};


module.exports = mongoose.model('verifications', schema);
2 changes: 1 addition & 1 deletion pages/exam/home.pug
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ block content
tr
th
span(style='display: inline-block;')
a(href=`/exam/paper?cid=${category._id}`)=`${category.name}`
a(href=`/exam/paper?cid=${category._id}` title=category.desc)=`${category.name}`
th
if category.volume === 'A'
span 基础级
Expand Down
Loading

0 comments on commit 7208ba0

Please sign in to comment.