驗證碼是Web應用中防止自動化攻擊的重要手段。下面我將詳細介紹如何使用Python實現一個完整的驗證碼系統(tǒng),包括生成、驗證和安全防護等關鍵環(huán)節(jié)。在Flask中集成驗證碼需存儲驗證碼文本并設置過期時間。前端通過接口獲取驗證碼圖片,用戶提交后比對輸入與存儲值。
python如何編寫驗證碼程序?
一、基礎驗證碼生成
1. 使用Pillow庫生成圖片驗證碼
pythonfrom PIL import Image, ImageDraw, ImageFont, ImageFilterimport randomimport stringimport osclass CaptchaGenerator:def __init__(self, width=120, height=40, char_num=4):self.width = widthself.height = heightself.char_num = char_num # 驗證碼字符數self.chars = string.ascii_letters + string.digits # 字符集def generate_image(self):# 創(chuàng)建空白圖像image = Image.new('RGB', (self.width, self.height), (255, 255, 255))draw = ImageDraw.Draw(image)# 生成隨機字符captcha_text = ''.join(random.choices(self.chars, k=self.char_num))# 設置字體try:font = ImageFont.truetype('arial.ttf', 24)except:font = ImageFont.load_default()# 繪制字符(添加隨機顏色和位置偏移)for i, char in enumerate(captcha_text):draw.text((10 + i * 25 + random.randint(-3, 3), 10 + random.randint(-5, 5)),char,fill=(random.randint(50, 150), random.randint(50, 150), random.randint(50, 150)),font=font)# 添加干擾元素self._add_noise(draw, image)# 添加扭曲效果image = self._warp_image(image)return image, captcha_textdef _add_noise(self, draw, image):# 添加干擾線for _ in range(3):draw.line([(random.randint(0, self.width), random.randint(0, self.height)),(random.randint(0, self.width), random.randint(0, self.height))],fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)),width=1)# 添加噪點for _ in range(50):draw.point([random.randint(0, self.width), random.randint(0, self.height)], fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))def _warp_image(self, image):# 創(chuàng)建扭曲效果width, height = image.sizenew_image = Image.new('RGB', (width, height))pixels = new_image.load()for x in range(width):for y in range(height):# 計算扭曲后的坐標new_x = int(x + (random.random() - 0.5) * 2)new_y = int(y + (random.random() - 0.5) * 2)# 確保坐標在圖像范圍內new_x = max(0, min(new_x, width - 1))new_y = max(0, min(new_y, height - 1))pixels[x, y] = image.getpixel((new_x, new_y))return new_image# 使用示例generator = CaptchaGenerator()image, text = generator.generate_image()image.save('captcha.png')print("驗證碼文本:", text)
二、Web集成與驗證
1. Flask集成示例
pythonfrom flask import Flask, session, make_response, request, jsonifyimport ioimport timeapp = Flask(__name__)app.secret_key = 'your_secret_key_here' # 必須設置密鑰# 驗證碼存儲字典(生產環(huán)境建議用Redis)captcha_store = {}@app.route('/captcha')def captcha():generator = CaptchaGenerator()img_io = io.BytesIO()image, text = generator.generate_image()image.save(img_io, 'PNG')img_io.seek(0)# 存儲驗證碼(設置5分鐘過期)captcha_id = str(time.time())captcha_store[captcha_id] = {'text': text,'expire': time.time() + 300 # 5分鐘后過期}response = make_response(img_io.getvalue())response.headers['Content-Type'] = 'image/png']response.headers['Captcha-Id'] = captcha_id # 返回驗證碼IDreturn [email protected]('/verify', methods=['POST'])def verify():data = request.get_json()captcha_id = data.get('captcha_id')user_input = data.get('captcha_text', '').strip().lower()# 檢查驗證碼是否存在且未過期captcha_data = captcha_store.get(captcha_id)if not captcha_data or time.time() > captcha_data['expire']:return jsonify({'success': False, 'message': '驗證碼已過期'})# 驗證并刪除已使用的驗證碼if user_input == captcha_data['text'].lower():del captcha_store[captcha_id]return jsonify({'success': True})else:return jsonify({'success': False, 'message': '驗證碼錯誤'})if __name__ == '__main__':app.run(debug=True)

三、進階功能與安全考慮
1. 使用專業(yè)庫簡化開發(fā)
python# 使用captcha庫(更簡單高效)from captcha.image import ImageCaptchadef generate_with_captcha_lib():image = ImageCaptcha(width=120, height=40)captcha_text = ''.join(random.choices(string.ascii_letters + string.digits, k=4))data = image.generate(captcha_text)image.write(captcha_text, 'captcha_lib.png')return captcha_text
2. 安全增強措施
驗證碼復雜度控制:
混合大小寫字母和數字
避免使用容易混淆的字符(如0/O, 1/l)
字符數建議在4-6個之間
防護措施:
限制驗證嘗試次數
驗證碼一次性使用,驗證后立即失效
記錄失敗嘗試,異常時觸發(fā)人機驗證
高級技術:
行為驗證:記錄用戶鼠標軌跡、點擊位置等
滑塊驗證碼:要求用戶拖動滑塊完成拼圖
短信/郵箱驗證碼:作為圖片驗證碼的補充
3. 生產環(huán)境建議
存儲方案:
使用Redis存儲驗證碼,設置過期時間
分布式環(huán)境下考慮使用共享存儲
性能優(yōu)化:
預生成驗證碼圖片模板
使用緩存減少重復計算
監(jiān)控與日志:
記錄驗證碼生成和驗證日志
監(jiān)控異常驗證行為
四、完整示例(簡化版)
python# 完整驗證碼服務類import redisimport timeimport hashlibclass CaptchaService:def __init__(self, redis_url='redis://localhost:6379/0'):self.redis = redis.from_url(redis_url)self.generator = CaptchaGenerator()def generate(self):image, text = self.generator.generate_image()# 生成唯一IDcaptcha_id = hashlib.sha256(str(time.time()).encode()).hexdigest()[:16]# 存儲到Redis,5分鐘過期self.redis.setex(f"captcha:{captcha_id}", 300, text.lower())# 返回二進制圖片和IDimg_bytes = io.BytesIO()image.save(img_bytes, format='PNG')return captcha_id, img_bytes.getvalue()def verify(self, captcha_id, user_input):if not captcha_id or not user_input:return False# 從Redis獲取驗證碼stored_text = self.redis.get(f"captcha:{captcha_id}")if not stored_text:return False# 驗證后刪除self.redis.delete(f"captcha:{captcha_id}")return user_input.lower() == stored_text.decode().lower()
Python實現驗證碼系統(tǒng)需要關注以下幾個方面:
驗證碼生成算法(字符集、干擾元素、扭曲效果)
存儲與驗證機制(一次性使用、過期時間)
安全防護措施(防暴力破解、防自動化)
生產環(huán)境部署(分布式存儲、性能優(yōu)化)
對于大多數應用,使用captcha等專業(yè)庫配合Redis存儲即可滿足需求。高安全要求的場景可以考慮結合多種驗證方式,如短信驗證碼+行為驗證等。完整系統(tǒng)需結合前端展示和后端存儲,并添加干擾措施提升安全性。