在前端开发中,防止用户重复提交表单是一个常见的问题。传统的解决方案是在服务端设置一个 token,每次提交表单时将 token 一并提交,服务端在接收到请求后会验证 token 的合法性,如果 token 已经被使用过了,就不允许再次提交。但是在 Serverless 架构中,由于服务端没有状态,这种方案就无法使用了。本文将介绍几种在 Serverless 架构中防止重复提交的方案。
方案一:利用数据库
在 Serverless 架构中,我们可以使用 NoSQL 数据库来保存 token 的状态,例如使用 AWS DynamoDB。每次提交表单时,我们将 token 存入数据库中,并设置一个过期时间。如果同一个 token 被使用过了,就不允许再次提交。具体实现可以参考以下示例代码:
// javascriptcn.com 代码示例 const AWS = require('aws-sdk'); const dynamoDb = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event) => { const token = event.token; const timestamp = Math.floor(Date.now() / 1000); const ttl = 60; // token 过期时间为 60 秒 // 将 token 存入 DynamoDB const params = { TableName: 'tokens', Item: { token: token, timestamp: timestamp, ttl: timestamp + ttl, }, ConditionExpression: 'attribute_not_exists(token)', }; try { await dynamoDb.put(params).promise(); } catch (err) { console.log(err); return { statusCode: 400, body: 'Token already used' }; } // 处理表单提交逻辑 // ... return { statusCode: 200, body: 'Success' }; };
方案二:利用缓存
在 Serverless 架构中,我们可以使用缓存来保存 token 的状态,例如使用 AWS Elasticache。每次提交表单时,我们将 token 存入缓存中,并设置一个过期时间。如果同一个 token 被使用过了,就不允许再次提交。具体实现可以参考以下示例代码:
// javascriptcn.com 代码示例 const AWS = require('aws-sdk'); const redis = require('redis'); const client = redis.createClient({ host: 'my-redis-cluster.xxxxxxx.ng.0001.apse1.cache.amazonaws.com', port: 6379, }); exports.handler = async (event) => { const token = event.token; const ttl = 60; // token 过期时间为 60 秒 // 将 token 存入缓存 const result = await new Promise((resolve, reject) => { client.set(token, 1, 'EX', ttl, 'NX', (err, res) => { if (err) { reject(err); } else if (res === 'OK') { resolve(true); } else { resolve(false); } }); }); if (!result) { return { statusCode: 400, body: 'Token already used' }; } // 处理表单提交逻辑 // ... return { statusCode: 200, body: 'Success' }; };
方案三:利用消息队列
在 Serverless 架构中,我们可以使用消息队列来保存 token 的状态,例如使用 AWS SQS。每次提交表单时,我们将 token 发送到消息队列中,并设置一个过期时间。如果同一个 token 被使用过了,就不允许再次提交。具体实现可以参考以下示例代码:
// javascriptcn.com 代码示例 const AWS = require('aws-sdk'); const sqs = new AWS.SQS(); exports.handler = async (event) => { const token = event.token; const timestamp = Math.floor(Date.now() / 1000); const ttl = 60; // token 过期时间为 60 秒 // 将 token 发送到消息队列中 const params = { QueueUrl: 'https://sqs.ap-southeast-1.amazonaws.com/xxxxxxxxxx/my-queue', MessageBody: token, MessageAttributes: { timestamp: { DataType: 'Number', StringValue: timestamp.toString(), }, ttl: { DataType: 'Number', StringValue: (timestamp + ttl).toString(), }, }, }; try { await sqs.sendMessage(params).promise(); } catch (err) { console.log(err); return { statusCode: 400, body: 'Token already used' }; } // 处理表单提交逻辑 // ... return { statusCode: 200, body: 'Success' }; };
总结
在 Serverless 架构中,由于服务端没有状态,防重复提交变得更加困难。但是我们可以利用数据库、缓存或消息队列来保存 token 的状态,从而实现防重复提交。需要注意的是,这些方案都需要考虑并发的情况,避免多个请求同时使用相同的 token。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65783ae4d2f5e1655d221e20