Python 2.7 可重复使用的cookies
我正在使用Python 2.7 可重复使用的cookies,python-2.7,flask,flask-login,Python 2.7,Flask,Flask Login,我正在使用Flask login和记住=False(唯一的cookie是会话cookie)。注销后复制粘贴会话cookie时,由于某些原因,会话仍然有效,用户已登录。即使注销会话已在flasklogout\u user()函数中正确删除-这意味着[“user\u id”]已从会话字典中删除。会话似乎是从旧cookie恢复的。有人能解释一下吗 我还没有一个正确的答案,因为我自己正在调查,但我想在这里提出几点: Flask登录的注销用户()似乎并没有真正使会话无效。它只是更改客户端(浏览器)中“会话
Flask login
和记住=False
(唯一的cookie是会话
cookie)。注销后复制粘贴会话
cookie时,由于某些原因,会话仍然有效,用户已登录。即使注销会话已在flasklogout\u user()
函数中正确删除-这意味着[“user\u id”]
已从会话
字典中删除。会话似乎是从旧cookie恢复的。有人能解释一下吗 我还没有一个正确的答案,因为我自己正在调查,但我想在这里提出几点:
Flask登录的注销用户()似乎并没有真正使会话无效。它只是更改客户端(浏览器)中“会话”cookie的值。在后端,此会话仍处于活动状态
证明这一点的实验是:(一个简单的浏览器插件,比如CookieManager,可以用来执行这个练习)
然而,我自己仍在研究并试图理解它 我也有这个问题。诊断后,我发现decorator@login\u required
*在注销后不会使服务器端的用户无效*
,这是一种安全威胁。这将是黑客破解你的应用程序的一个小菜一碟,因为他们可以很容易地从你浏览器的开发者工具中提取所有请求和标题数据,并且可以再次从应用程序外部向你的服务器发送请求。例如:如果你在应用程序中使用了任何API,黑客将很容易获得所有请求数据并使用邮递员重新发送请求
我通过创建一个单独的装饰程序“@authentication\u required”来解决这个问题,并用它代替“@login\u required”。虽然@login\u required也应该这样做,但它对我来说很有效。
因此,基本上在登录时,我生成了一个随机字符串(令牌)并发送到数据库,相同的字符串(令牌)被添加到flask的会话中,即session[“token”]=“akhfkjdbfnd334fndf”使用任意随机字符串生成器函数。(如果使用flask,session对象是全局可用的。您可以很好地向会话添加任何字段)。在注销时,我再次生成一个字符串(令牌),并用数据库中新生成的令牌更新旧令牌。所以@authentication_required将做的是从会话对象和数据库中存在的令牌中获取令牌,并尝试比较值。如果两者相同,则只有@authentication\u required允许客户端访问api。并且在注销\u user()后不要忘记执行session.clear()
-------------------------------------------------------
登录api代码
注意:似乎需要登录对我来说不太好,这就是为什么我必须创建另一个装饰器,但需要登录也做同样的事情,但奇怪的是它对我不起作用。谢谢!我发现了一些很好的文档,用于通过
flask登录应用会话管理。基本上,我将基于id
的令牌替换为基于session
的令牌,该令牌在用户登录和注销时创建和销毁。
#---------------------------------------------------------------#
#@authentication_required definition
def authentication_required(f):
@wraps(f)
def wrap(*args, **kwargs):
try:
user_id=session['user_id'] #assigning "user_id" from flask session object to a variable "user_id"
user=User_table.find_first(_id=user_id)#couhdb query syntax
#comparing api_token sent to session object at the login time with api_token in sent to database at login time. If both doesn't matches then user is redirected to login page.
if not session["token"]==user.token:
return redirect(url_for('login'))
else:
return f(*args, **kwargs)
except:
app.logger.info(Response('Request Did not came through header !', 401, {'WWW-Authenticate': 'Login failed'}))
return redirect(url_for('login_to system'))
return wrap
#---------------------------------------------------------------#
@app.route('/login_to_system', methods=['GET', 'POST'])
def login_to_system():
form = LoginForm()
user = User_table.find_first(username=form.username.data)
login_user(user, remember=False)
try:
#Generating an random api_token at login time and will send to db
token_string=''.join(random.choices(string.ascii_uppercase + string.digits, k=14))
user.token=token_string #assigning token_string value to field api_token in database.
user.save() #saving the value in user table(using couch Db You can follow syntax as per you DB)
except Exception as error:
app.logger.error(str(error))
app.logger.info("before setting api_token in session")
session["token"]= token_string #adding a "token" to session object
#app.logger.info("Rendering login form")
return render_template('login.html', title='Sign In', form=form)
#-------------------------------------------------------#
#-----------------------------------#
#logout api code
@app.route('/logout')
def logout():
try:
user=User_table.find_first(_id=user_id)
#Generating a random token while logging out and will overwrite eariler token sent at login time send to database.
user.token=token_string=''.join(random.choices(string.ascii_uppercase + string.digits, k=17))
user.save()
except Exception as error:
app.logger.error(str(error))
logout_user()
session.clear()#clearing session
return redirect(url_for('Home page'))
#-----------------------------------#