Python 如何从会话中删除特定密钥(用于当前会话)?

Python 如何从会话中删除特定密钥(用于当前会话)?,python,session,flask,flask-login,flask-kvsession,Python,Session,Flask,Flask Login,Flask Kvsession,我使用Flask kvsession来避免重播攻击,因为Flask登录使用的基于客户端cookie的会话很容易受到重播攻击。 例如:如果在/索引页面上,标题中的cookie是为应用标题设置的,如 myapp_会话:“值1” 如果您导航到/important页面,您将得到一个新的标题,如 myapp_会话:“value2”,因此如果黑客获得“value1”,他可以执行重播攻击并滥用它,因为它永远不会失效 为了解决这个问题,我使用了flask kvsession,它将会话cookie头值存储在缓存或

我使用Flask kvsession来避免重播攻击,因为Flask登录使用的基于客户端cookie的会话很容易受到重播攻击。 例如:如果在/索引页面上,标题中的cookie是为应用标题设置的,如 myapp_会话:“值1” 如果您导航到/important页面,您将得到一个新的标题,如 myapp_会话:“value2”,因此如果黑客获得“value1”,他可以执行重播攻击并滥用它,因为它永远不会失效

为了解决这个问题,我使用了flask kvsession,它将会话cookie头值存储在缓存或某个后端中。因此,基本上只有一个myapp_会话在您注销时生成并失效。但问题是:-

__init__.py 

from simplekv.memory.redisstore import RedisStore
import redis

store = RedisStore(redis.StrictRedis())
#store = memcache.Client(['127.0.0.1:11211'], debug =0)
store.ttl_support = True
app = create_app(__name__)
current_kvsession = KVSessionExtension(store, app)
如果您查看kv会话代码的cleanup_会话部分

它只删除过期的会话。但是,如果我想在注销时为特定用户显式删除当前myapp_会话的值,我该怎么做

@app.before_request
def redirect_if_logout():
  if request.path == url_for('logout'):
      for key in app.kvsession_store.keys():
        logger.debug(key)
        m = current_kvsession.key_regex.match(key)
        logger.debug('found %s', m)
        app.kvsession_store.delete(key)
但这会删除所有密钥,因为我不知道当前会话的唯一密钥是什么


问题2。另外,如何使用memcache而不是redis,因为它没有app.kvsession\u store.keys()函数,并且会出现i/o错误。

我想我刚刚了解了您问题的第一部分,即如何在注销时删除特定的密钥

如文件所述:

在内部,会话存储序列化为的会话ID 已创建密钥,其中密钥是一个随机数(会话“true”id)和 创建会话创建时间的UNIX时间戳

在客户端创建的cookie值示例(您可以使用firefox的cookie管理器扩展进行检查):

c823af88aedaf496_571b3fd5.4kv9X8UvyQqtCtNV87jTxy3Zcqc

和作为密钥存储在redis中的会话id:

c823af88aedaf496_571b3fd5

因此,在注销处理程序上,您只需要读取cookie值,拆分它并使用字符串的第一部分:

适用于我的示例代码:

import redis
from flask import Flask
from flask_kvsession import KVSessionExtension
from simplekv.memory.redisstore import RedisStore

store = RedisStore(redis.StrictRedis())

app = Flask(__name__)
KVSessionExtension(store, app)

#Logout Handler
@app.route('/logout', methods=['GET'])
def logout():
    #here you are reading the cookie 
    cookie_val = request.cookies.get('session').split(".")[0]
    store.delete(cookie_val)
由于您添加了ttl_支持:

store.ttl_support = True
如果您在配置文件或app.py文件的开头设置了TTL(秒),它将与永久会话生命周期中的TTL(秒)值相匹配

例如,在我的应用程序中,我在app.py文件的开头设置为:

session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=5)
现在,当我注销时,它会删除redis中的密钥,但直到该密钥的TTL从300变为0(永久会话生存期值中提到的5分钟),它才会被删除

如果您想立即将其从redis中删除,您可以手动将app.permanent_session_生存期更改为1秒,这将反过来更改redis的TTL

import redis
import os
from flask import Flask
from flask_kvsession import KVSessionExtension
from simplekv.memory.redisstore import RedisStore

store = RedisStore(redis.StrictRedis())

app = Flask(__name__)
KVSessionExtension(store, app)

#Logout Handler
@app.route('/logout', methods=['GET'])
def logout():
    cookie_val = request.cookies.get('session').split(".")[0]
    app.permanent_session_lifetime = timedelta(seconds=1)
    store.delete(cookie_val)
使用上述代码,我能够阻止会话重播攻击

第二个问题的答案:

我看到的3个可能的错误是:

1:在您创建的代码的开头:

store = RedisStore(redis.StrictRedis())
但在循环中,您将其用作kvsession_存储,而不仅仅是存储:

app.kvsession_store.keys()
  • 要在没有任何错误/异常的情况下使用它,您可以将其用作
    store.keys()
    而不是app.store.keys():

  • store.delete(key)
    并不是删除所有的键,而是在一个接一个删除所有键的循环中运行它

  • from flask_kvsession import KVSessionExtension
    from simplekv.memory.redisstore import RedisStore
    store = RedisStore(redis.StrictRedis())
    
    for key in store.keys():
        print key