Python Flask:跟踪用户会话?如何获取会话 Cookie ID? [英] Python Flask: keeping track of user sessions? How to get Session Cookie ID?
问题描述
我想构建一个简单的网络应用程序作为我学习活动的一部分.如果 Webapp 遇到第一次访问者,它应该要求用户输入他们的 email_id,否则它会通过 cookie 记住用户并自动让他/她登录以执行这些功能.
I want to build a simple webapp as part of my learning activity. Webapp is supposed to ask for user to input their email_id if it encounters a first time visitor else it remembers the user through cookie and automatically logs him/her in to carry out the functions.
这是我第一次创建基于用户的网络应用程序.我有一个蓝图,但我无法弄清楚如何实施它.主要是我对收集用户 cookie 的方式感到困惑.我查看了各种教程和flask_login,但我认为与flask_login正在实现的相比,我想要实现的要简单得多.
This is my first time with creating a user based web app. I have a blue print in my mind but I am unable to figure out how to implement it. Primarily I am confused with respect to the way of collecting user cookie. I have looked into various tutorials and flask_login but I think what I want to implement is much simpler as compared to what flask_login is implementing.
我也尝试过使用 flask.session
但它有点难以理解,最终我得到了一个有缺陷的实现.
I also tried using flask.session
but it was a bit difficult to understand and I ended up with a flawed implementation.
到目前为止,这是我所拥有的(它是基本的,旨在传达我的用例):
Here is what I have so far (it is rudimentary and meant to communicate my use case):
from flask import render_template, request, redirect, url_for
@app.route("/", methods= ["GET"])
def first_page():
cookie = response.headers['cookie']
if database.lookup(cookie):
user = database.get(cookie) # it returns user_email related to that cookie id
else:
return redirect_url(url_for('login'))
data = generateSomeData() # some function
return redirect(url_for('do_that'), user_id, data, stats)
@app.route('/do_that', methods =['GET'])
def do_that(user_id):
return render_template('interface.html', user_id, stats,data) # it uses Jinja template
@app.route('/submit', methods =["GET"])
def submit():
# i want to get all the information here
user_id = request.form['user_id']# some data
answer = request.form['answer'] # some response to be recorded
data = request.form['data'] # same data that I passed in do_that to keep
database.update(data,answer,user_id)
return redirect(url_for('/do_that'))
@app.route('/login', methods=['GET'])
def login():
return render_template('login.html')
@app.route('/loggedIn', methods =['GET'])
def loggedIn():
cookie = response.headers['cookie']
user_email = response.form['user_email']
database.insert(cookie, user_email)
return redirect(url_for('first_page'))
推荐答案
您可以通过 request.cookies
字典 并使用 make_response
或仅存储调用 render_template的结果来设置 cookiecode> 在一个变量中,然后调用
set_cookie
在响应对象上:
You can access request cookies through the request.cookies
dictionary and set cookies by using either make_response
or just storing the result of calling render_template
in a variable and then calling set_cookie
on the response object:
@app.route("/")
def home():
user_id = request.cookies.get('YourSessionCookie')
if user_id:
user = database.get(user_id)
if user:
# Success!
return render_template('welcome.html', user=user)
else:
return redirect(url_for('login'))
else:
return redirect(url_for('login'))
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
# You should really validate that these fields
# are provided, rather than displaying an ugly
# error message, but for the sake of a simple
# example we'll just assume they are provided
user_name = request.form["name"]
password = request.form["password"]
user = db.find_by_name_and_password(user_name, password)
if not user:
# Again, throwing an error is not a user-friendly
# way of handling this, but this is just an example
raise ValueError("Invalid username or password supplied")
# Note we don't *return* the response immediately
response = redirect(url_for("do_that"))
response.set_cookie('YourSessionCookie', user.id)
return response
@app.route("/do-that")
def do_that():
user_id = request.cookies.get('YourSessionCookie')
if user_id:
user = database.get(user_id)
if user:
# Success!
return render_template('do_that.html', user=user)
else:
return redirect(url_for('login'))
else:
return redirect(url_for('login'))
干掉代码
现在,您会注意到 home
和 do_that
方法中有很多样板文件,所有这些都与登录相关.您可以通过编写自己的装饰器来避免这种情况(如果您想,请参阅 什么是装饰器详细了解它们):
DRYing up the code
Now, you'll note there is a lot of boilerplate in the home
and do_that
methods, all related to login. You can avoid that by writing your own decorator (see What is a decorator if you want to learn more about them):
from functools import wraps
from flask import flash
def login_required(function_to_protect):
@wraps(function_to_protect)
def wrapper(*args, **kwargs):
user_id = request.cookies.get('YourSessionCookie')
if user_id:
user = database.get(user_id)
if user:
# Success!
return function_to_protect(*args, **kwargs)
else:
flash("Session exists, but user does not exist (anymore)")
return redirect(url_for('login'))
else:
flash("Please log in")
return redirect(url_for('login'))
return wrapper
然后你的 home
和 do_that
方法变得大大:
Then your home
and do_that
methods get much shorter:
# Note that login_required needs to come before app.route
# Because decorators are applied from closest to furthest
# and we don't want to route and then check login status
@app.route("/")
@login_required
def home():
# For bonus points we *could* store the user
# in a thread-local so we don't have to hit
# the database again (and we get rid of *this* boilerplate too).
user = database.get(request.cookies['YourSessionCookie'])
return render_template('welcome.html', user=user)
@app.route("/do-that")
@login_required
def do_that():
user = database.get(request.cookies['YourSessionCookie'])
return render_template('welcome.html', user=user)
使用所提供的
如果您不需要您的 cookie 具有特定名称,我建议使用 flask.session
因为它已经内置了很多细节(它已经签名所以不能被篡改,可以设置为仅限 HTTP 等).这使我们的 login_required
装饰器更加干燥:
Using what's provided
If you don't need your cookie to have a particular name, I would recommend using flask.session
as it already has a lot of niceties built into it (it's signed so it can't be tampered with, can be set to be HTTP only, etc.). That DRYs up our login_required
decorator even more:
# You have to set the secret key for sessions to work
# Make sure you keep this secret
app.secret_key = 'something simple for now'
from flask import flash, session
def login_required(function_to_protect):
@wraps(function_to_protect)
def wrapper(*args, **kwargs):
user_id = session.get('user_id')
if user_id:
user = database.get(user_id)
if user:
# Success!
return function_to_protect(*args, **kwargs)
else:
flash("Session exists, but user does not exist (anymore)")
return redirect(url_for('login'))
else:
flash("Please log in")
return redirect(url_for('login'))
然后您的个人方法可以通过以下方式获取用户:
And then your individual methods can get the user via:
user = database.get(session['user_id'])
这篇关于Python Flask:跟踪用户会话?如何获取会话 Cookie ID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!