You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在删除浏览器历史与缓存后保留Flask会话以限制非注册用户使用次数?

解决方案

1. 基于IP地址的服务器端追踪

这种方式把用户的使用次数和过期时间存在服务器端(比如Redis或数据库),完全不依赖客户端缓存,从根源上避免用户清缓存重置次数的问题。

实现步骤:

  • 安装Redis或用SQLite/MySQL做存储
  • 后端获取用户真实公网IP(要考虑反向代理场景)
  • 每次请求时校验该IP当日的使用次数,超过5次就拒绝

代码示例:

Flask后端(用Redis):

from flask import Flask, request, jsonify
import redis
from datetime import datetime, timedelta

app = Flask(__name__)
# 初始化Redis连接
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

def get_real_ip():
    # 兼容反向代理(比如Nginx)的情况
    if request.headers.get('X-Forwarded-For'):
        return request.headers.get('X-Forwarded-For').split(',')[0].strip()
    return request.remote_addr

@app.route('/api/summarize', methods=['POST'])
def handle_summarize():
    user_ip = get_real_ip()
    today = datetime.now().strftime('%Y-%m-%d')
    # 构造当日使用记录的key
    record_key = f"daily_usage:{user_ip}:{today}"
    
    current_count = int(r.get(record_key) or 0)
    if current_count >= 5:
        return jsonify({'status': 'fail', 'msg': '今日使用次数已达上限,请明日再试'}), 403
    
    # 这里写你的文本摘要逻辑
    summary_result = "生成的摘要内容"
    
    # 增加使用次数,并设置过期时间到次日凌晨
    r.incr(record_key)
    tomorrow = datetime.now() + timedelta(days=1)
    expire_at = datetime(tomorrow.year, tomorrow.month, tomorrow.day, 0, 0, 0)
    r.expireat(record_key, expire_at)
    
    return jsonify({'status': 'success', 'summary': summary_result, 'remaining': 5 - current_count - 1})

if __name__ == '__main__':
    app.run(debug=True)

前端Ajax请求:

function submitTextForSummary() {
    const inputText = document.getElementById('input-content').value;
    fetch('/api/summarize', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({'text': inputText})
    })
    .then(res => res.json())
    .then(data => {
        if (data.status === 'fail') {
            alert(data.msg);
        } else {
            document.getElementById('summary-output').innerText = data.summary;
            document.getElementById('remaining-count').innerText = `今日剩余次数:${data.remaining}`;
        }
    })
    .catch(err => console.error('请求出错:', err));
}

缺点:同一公网IP下的多个用户会共享次数(比如公司、家庭局域网),可能误伤正常用户。


2. 基于设备指纹的服务器端追踪

通过前端提取浏览器和设备的特征生成唯一指纹,服务器端存储这个指纹对应的使用记录。即使用户清空缓存,只要设备/浏览器的核心特征不变,就能识别出是同一个用户。

实现步骤:

  • 前端组合浏览器UA、屏幕分辨率、时区等特征生成指纹
  • 请求时把指纹传给后端,后端校验该指纹的当日使用次数

代码示例:

前端生成指纹:

function createDeviceFingerprint() {
    // 组合多个设备/浏览器特征
    const deviceFeatures = [
        navigator.userAgent,
        `${screen.width}x${screen.height}`,
        Intl.DateTimeFormat().resolvedOptions().timeZone,
        navigator.language,
        navigator.platform
    ];
    // 简单转成base64作为指纹
    return btoa(deviceFeatures.join('|'));
}

function submitTextForSummary() {
    const inputText = document.getElementById('input-content').value;
    const fingerprint = createDeviceFingerprint();
    
    fetch('/api/summarize', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({'text': inputText, 'fingerprint': fingerprint})
    })
    .then(res => res.json())
    .then(data => {
        if (data.status === 'fail') {
            alert(data.msg);
        } else {
            document.getElementById('summary-output').innerText = data.summary;
            document.getElementById('remaining-count').innerText = `今日剩余次数:${data.remaining}`;
        }
    })
    .catch(err => console.error('请求出错:', err));
}

Flask后端(用Redis):

from flask import Flask, request, jsonify
import redis
from datetime import datetime, timedelta

app = Flask(__name__)
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

@app.route('/api/summarize', methods=['POST'])
def handle_summarize():
    req_data = request.get_json()
    fingerprint = req_data.get('fingerprint')
    
    if not fingerprint:
        return jsonify({'status': 'fail', 'msg': '无效请求'}), 400
    
    today = datetime.now().strftime('%Y-%m-%d')
    record_key = f"daily_usage:fingerprint:{fingerprint}:{today}"
    
    current_count = int(r.get(record_key) or 0)
    if current_count >= 5:
        return jsonify({'status': 'fail', 'msg': '今日使用次数已达上限,请明日再试'}), 403
    
    # 文本摘要逻辑
    summary_result = "生成的摘要内容"
    
    r.incr(record_key)
    tomorrow = datetime.now() + timedelta(days=1)
    expire_at = datetime(tomorrow.year, tomorrow.month, tomorrow.day, 0, 0, 0)
    r.expireat(record_key, expire_at)
    
    return jsonify({'status': 'success', 'summary': summary_result, 'remaining': 5 - current_count - 1})

if __name__ == '__main__':
    app.run(debug=True)

缺点:设备指纹不是绝对唯一的,极端情况不同设备可能生成相同指纹,或者同一设备升级浏览器后指纹变化,但比单纯用IP精准得多。


3. IP+设备指纹混合方案

结合两种方式,优先用设备指纹识别用户,指纹不存在时 fallback 到IP记录,能最大程度减少误判。

核心逻辑:

  • 前端同时传指纹和IP给后端
  • 后端先查指纹对应的记录,没有的话再查IP的记录
  • 记录时可以把指纹和IP关联起来,后续请求优先匹配指纹

额外优化建议

  • 实时显示剩余次数:后端返回剩余次数字段,前端展示给用户,提升体验
  • 处理动态IP:允许同一指纹关联多个IP,避免用户IP变动导致次数重置
  • 防滥用:对频繁切换指纹/IP的请求,加入验证码验证

内容的提问来源于stack exchange,提问作者ficiency business

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 09:46:04