切换主题
字数
660 字
阅读时间
3 分钟
让我来详细解释 IP 限制功能的实现:
1 数据库设计:
在 MongoDB 中设计了两个相关的 Schema:
- 问卷 Schema (question.schema.ts):
@Prop({ default: 99 }) // 默认99次
ipLimit: number;
- IP 记录 Schema (ip-record.schema.ts):
@Schema({
timestamps: true,
})
export class IpRecord {
@Prop({ required: true })
questionId: string;
@Prop({ required: true })
ip: string;
@Prop({ required: true, default: 1 })
count: number;
}
2 中间件实现 (ip-limit.middleware.ts):
@Injectable()
export class IpLimitMiddleware implements NestMiddleware {
async use(req: Request, res: Response, next: NextFunction) {
const questionId = req.body.questionId;
const ip = req.ip;
// 1. 获取问卷信息和 IP 限制次数
const question = await this.questionService.findOne(questionId);
const ipLimit = question.ipLimit;
// 2. 查找或创建 IP 记录
let ipRecord = await this.ipRecordModel.findOne({ questionId, ip });
// 3. 检查是否超过限制
if (ipRecord && ipRecord.count >= ipLimit) {
throw new HttpException('答题次数已达上限', HttpStatus.FORBIDDEN);
}
// 4. 更新访问次数
await this.ipRecordModel.findOneAndUpdate(
{ questionId, ip },
{ $inc: { count: 1 } },
{ upsert: true, new: true },
);
next();
}
}
3 前端设置界面 (PageSetting.tsx):
<Form.Item label="问卷限制" name="ipLimit">
<InputNumber min={0} />
</Form.Item>
4 后端 API 接口 (question.controller.ts):
@Patch(':id/ip-limit')
async updateIpLimit(
@Param('id') id: string,
@Body('ipLimit') ipLimit: number,
@Request() req,
) {
const { username } = req.user;
if (!ipLimit || ipLimit < 1) {
throw new HttpException('IP限制次数必须大于0', HttpStatus.BAD_REQUEST);
}
return await this.questionService.update(id, { ipLimit }, username);
}
5 工作流程:
a) 设置阶段:
问卷创建者可以在问卷设置中设置 IP 限制次数
默认值为 99 次
通过 API 将设置保存到数据库
b) 答卷阶段:
用户提交问卷时,中间件会自动拦截请求
获取用户 IP 和问卷 ID
检查该 IP 的答题次数是否超过限制
如果超过限制,返回 403 错误
如果未超过限制,增加答题次数并继续处理请求
6 错误处理:
当用户超过答题次数限制时,会收到 403 状态码
错误响应格式:
{
"errno": -1,
"message": "答题次数已达上限",
"timestamp": "2024-05-01T12:00:00.000Z",
"path": "/api/answer"
}
7 安全考虑:
使用 Nginx 配置确保获取真实 IP
使用中间件统一处理,避免绕过限制
数据库层面使用事务确保数据一致性
这个功能的实现考虑了以下几个关键点:
性能:使用 MongoDB 的 upsert 操作,减少查询次数
安全性:中间件统一处理,不易绕过
用户体验:友好的错误提示
可配置性:问卷创建者可以自定义限制次数
可靠性:使用数据库记录,保证数据持久化
贡献者
sunchengzhi