Python Flask: отслеживание сеансов пользователей? Как получить идентификатор Cookie сеанса?
Я хочу создать простой webapp как часть моей учебной деятельности. Webapp должен попросить пользователя ввести свой email_id, если он встречает первого посетителя, иначе он запоминает пользователя через cookie и автоматически регистрирует его/ее для выполнения функций.
Это мой первый раз с созданием пользовательского веб-приложения. У меня в голове синяя печать, но я не могу понять, как ее реализовать. В первую очередь меня смущает способ сбора пользователя cookie. Я посмотрел на различные учебники и flask_login но я думаю, что я хочу реализовать гораздо проще по сравнению с чем flask_login реализует.
Я также попытался с помощью flask.session, но это было немного трудно понять, и я оказался с недостатками реализации.
вот что у меня есть до сих пор (это рудиментарно и предназначено для передачи моего варианта использования):
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'))
1 ответов
вы можете получить доступ к cookies запроса через request.cookies словарь и установить cookie с помощью make_response или просто сохранение результата вызова render_template в переменной, а затем вызов set_cookie на объекте ответа:
@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 методы, все связанные с входом в систему. Вы можете избежать этого, написав свой собственный декоратор (см. что такое декоратор если вы хотите узнать больше о них):
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 методы get много короче:
# 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 декоратор еще больше:
# 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'))
и тогда ваши индивидуальные методы могут получить пользователя через:
user = database.get(session['user_id'])