You need to enable JavaScript to run this app. PyMongo无需用户名访问哈希token实现登录校验的方法咨询
优惠活动
大模型
产品
解决方案
定价
更多

PyMongo无需用户名访问哈希token实现登录校验的方法咨询

问题原因

你代码运行失败是由4个核心错误导致的:

  • 变量名错误:你定义的集合变量是tokens_collection,但查询时错误使用了未定义的tokens变量,会直接抛出异常
  • 查询逻辑错误:库中存储的是bcrypt哈希后的token值,而你直接用用户提交的明文token作为查询条件。bcrypt哈希会自动添加随机盐,相同明文每次生成的哈希值完全不同,所以永远查不到匹配的文档,user_login始终为None
  • 字段名不一致:查询时用的键是tokens,后续取值用的是user_login['token'],单复数不匹配,就算查到也会报KeyError
  • 编码缺失:bcrypt比对要求两个参数都是字节类型,你没有对库中取出的哈希字符串做utf-8编码转换,会触发类型错误

解决方案

bcrypt是单向哈希算法,无法通过明文反查哈希值,因此你不能直接用明文token查询数据库,需要调整存储和查询逻辑:

第一步:调整token存储逻辑

写入token到数据库时,额外存储token的前6位明文作为查询前缀:

import bcrypt

# 生成用户原始token
raw_token = "生成的随机用户token"
# 计算bcrypt哈希
hashed_token = bcrypt.hashpw(raw_token.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
# 取前6位作为查询前缀
token_prefix = raw_token[:6]

# 写入数据库
tokens_collection.insert_one({
    "token_prefix": token_prefix,
    "hashed_token": hashed_token,
    "user_id": "关联的用户ID" # 可按需添加其他用户字段
})

第二步:修正登录验证逻辑

先通过token前缀查询到候选记录,再逐一做bcrypt比对:

@app.route('/account_login', methods=['POST'])
def account_login():
    try:
        if request.method == 'POST':
            tokens_collection = mongo.db.user_tokens
            raw_input_token = request.form.get('token', '').strip()
            if not raw_input_token:
                flash('Token不能为空')
                return redirect(url_for("account"))
            
            # 用前缀查询候选记录
            input_prefix = raw_input_token[:6]
            matched_token_docs = tokens_collection.find({"token_prefix": input_prefix})
            
            login_success = False
            current_user_id = None
            for doc in matched_token_docs:
                stored_hash = doc['hashed_token'].encode('utf-8')
                input_bytes = raw_input_token.encode('utf-8')
                if bcrypt.hashpw(input_bytes, stored_hash) == stored_hash:
                    login_success = True
                    current_user_id = doc['user_id']
                    break
            
            if login_success:
                # 不要存储明文token到session,存用户ID即可
                session['user_id'] = current_user_id
                return redirect(url_for("account"))
            
            flash('Token输入错误,请重新输入')
            return redirect(url_for("account"))
        return redirect(url_for("account"))
    except Exception as e:
        print(f"account login error: {e}")
        flash('系统异常,请稍后重试')
        return redirect(url_for("account"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 07:24:03