我正在使用 Flask-login
,并且设置了 remember=False
(唯一的cookie是 session
cookie)。
在退出登录后,当复制并粘贴 session
cookie 时,某种原因导致会话仍然有效,用户仍处于登录状态。尽管已经正确地从 flask 的 logout_user()
函数中删除了已注销的会话,也就是从 session
字典中删除了["user_id"]
。似乎会话是从旧的cookie中恢复的。有人可以解释一下吗?
我正在使用 Flask-login
,并且设置了 remember=False
(唯一的cookie是 session
cookie)。
在退出登录后,当复制并粘贴 session
cookie 时,某种原因导致会话仍然有效,用户仍处于登录状态。尽管已经正确地从 flask 的 logout_user()
函数中删除了已注销的会话,也就是从 session
字典中删除了["user_id"]
。似乎会话是从旧的cookie中恢复的。有人可以解释一下吗?
Flask-login中的logout_user()似乎并没有真正使会话失效。它只是更改了客户端(浏览器)中“session” cookie的值。而在后端,此会话仍然存在。
证明这一点的实验可以是:(可以使用类似CookieManager的简单浏览器插件来执行此操作)
结果:您将成功查看内部页面,而无需重新登录,证明logout_user()从未真正使会话无效,而只是更改了客户端中的“session” cookie。
然而,我自己仍在查看flask-login logout_user() definition并试图理解它。我也遇到了这个问题。经过诊断,我发现装饰器@login_required*在注销后不会在服务器端使用户失效*
,这是一个安全威胁。这将成为黑客攻击您的应用程序的一件轻而易举的事情,因为他们可以轻松地从浏览器的开发人员工具中提取所有请求和标头数据,并可以再次从应用程序外部向您的服务器发送请求。例如:如果您在应用程序中使用了任何API,则黑客很容易获取所有请求数据并使用POSTMAN重新发送请求。
#---------------------------------------------------------------#
#@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'))
#-----------------------------------#