NodeJS表单防垃圾请求咨询:如何拦截批量恶意提交?
Hey, sorry to hear you're dealing with this flood of spam requests from Python's requests library—especially since the attackers are smart enough to spoof User Agents and use proxies to get around basic limits. Let's break down some solid Node.js solutions (and handy npm packages) to lock this down, plus tweak your existing route code to implement them:
1. CAPTCHA Validation (Non-Interactive or User-Facing)
Since attackers are using automated tools, adding a CAPTCHA layer blocks bots while minimizing friction for real users:
- reCAPTCHA v3: Uses behavioral analysis to score requests without requiring users to click boxes. Use the
recaptcha-v3npm package to integrate it. In your POST route, first verify the token sent from the frontend—only proceed if the score meets your threshold (e.g., >0.5). - hCaptcha: A privacy-focused alternative to reCAPTCHA. Use the
hcaptchanpm package for integration, with similar token-based validation logic.
2. Rate Limiting (Stop Bulk Requests Cold)
This is non-negotiable for blocking 500+ rapid requests. These packages work seamlessly with Express:
- express-rate-limit: The go-to rate-limiting middleware for Express. You can restrict requests per IP, or even per authenticated user if you have a login system. For example, limit users to 10 POST requests per minute.
- rate-limit-redis: Pair this with
express-rate-limitif you're running multiple server instances—stores rate-limit counts in Redis to keep restrictions consistent across your infrastructure.
Example Implementation for Your Route
First install the package:
npm install express-rate-limit
Then update your route to include the limiter:
const rateLimit = require('express-rate-limit'); // Configure rate limiting: 10 requests per minute per IP const postRequestLimiter = rateLimit({ windowMs: 60 * 1000, // 1 minute window max: 10, // Max 10 requests per IP message: 'Too many requests—please try again in a minute.', standardHeaders: true, legacyHeaders: false, }); // Apply the limiter to your POST route app.post('/:id', postRequestLimiter, function(req, res){ if(req.method === 'POST') { const id = req.params.id; if(!isNaN(id)) { // FIX: Use parameterized queries to prevent SQL injection! db.query('SELECT * FROM users WHERE id = ?', [id], function(loggerErr, logger) { if(!loggerErr) { db.query(/* Your SQL query here */, function(logErr, logRes) { if(!logErr) { res.redirect('/'); } else { throw logErr; } }); } }); } else { db.query(/* Your SQL query here */, function(logErr, logRes) { if(!logErr) { res.redirect('/'); } else { throw logErr; } }); } } });
3. CSRF Token Validation
For user-submitted forms, CSRF tokens ensure requests come from your legitimate frontend (not automated bots). Use the csurf package:
Example Setup
Install dependencies first:
npm install csurf cookie-parser
Then configure and apply to your routes:
const cookieParser = require('cookie-parser'); const csrf = require('csurf'); // Initialize CSRF protection (stores tokens in cookies) const csrfProtection = csrf({ cookie: true }); // Use cookie-parser before CSRF middleware app.use(cookieParser()); // Pass CSRF token to your form template in GET routes app.get('/form/:id', csrfProtection, function(req, res) { // In your template, add a hidden input: <input type="hidden" name="_csrf" value="{{csrfToken}}"> res.render('your-form-template', { csrfToken: req.csrfToken() }); }); // Validate CSRF token in your POST route app.post('/:id', csrfProtection, function(req, res){ // Your existing logic here (plus rate limiting if combined) });
4. Behavioral & Header Analysis
Even with proxies and spoofed UAs, bots often leave telltale signs:
- express-useragent: Parse User Agent strings to flag suspiciously generic or malformed UAs. Combine this with checks for missing
Refererheaders or abnormally fast request intervals to block bots. - Custom anomaly detection: Track request timing per IP—if an IP sends requests every <100ms consistently, it's almost certainly automated. Temporarily block these IPs for 1-2 hours.
Critical Bonus Fix: SQL Injection Vulnerability
Wait a second—your current code has a huge SQL injection risk! This line:
db.query('SELECT * FROM users WHERE id = "'+id+'"'
An attacker could pass an ID like 1" OR 1=1 -- to access all user data. Always use parameterized queries (like the example I updated above) to sanitize inputs.
Pro Tip
Combine multiple layers of protection (rate limiting + CSRF + CAPTCHA for high-risk actions) to make it exponentially harder for attackers to bypass your defenses.
内容的提问来源于stack exchange,提问作者marki00

