Python瓶:跟踪用户会话?如何获得会话Cookie ID? [英] Python Flask: keeping track of user sessions? How to get Session Cookie ID?

查看:191
本文介绍了Python瓶:跟踪用户会话?如何获得会话Cookie ID?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为我学习活动的一部分,我想构建一个简单的web应用程序。 Web应用程序应该要求用户输入他们的email_id,如果遇到第一次访问者,它会通过cookie记住用户,并自动记录他/她执行的功能。

这是我第一次创建一个基于用户的web应用程序。我在脑海中有一个蓝图,但我无法弄清楚如何实现它。主要是我对收集用户cookie的方式感到困惑。我已经看过各种教程和flask_login,但我认为我想要实现的是比flask_login实现的要简单得多。



这是我到目前为止(这是基本的,意在沟通我的用例):

  from flask import render_template,request,redirect,url_for 

$ b $ app_route(/,methods = [GET])
def first_page():
cookie = response.headers ['cookie']
如果database.lookup(cookie):
user = database.get(cookie)#它返回user_email相关这个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)#它使用Jinja模板

@ app.route('/ submit',methods = [GET])
def submit() :
#我想在这里获取所有的信息
user_id = request.form ['user_id']#some data
answer = req我有一个数据库,这个数据库是一个数据库, 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('您可以通过以下方式访问请求Cookie:
/ code>


解决方案

request.cookies 字典,并通过使用 make_response 来设置cookie,或者只是将调用结果 render_template 然后调用 set_cookie
$ p $ @ app.route(/)
def home():
user_id = request.cookies.get('YourSessionCookie')
如果user_id:
user = database.get(user_id)
如果用户:
#成功!
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():
如果request.method ==POST:
#你应该确实提供这些字段
#,而不是显示丑陋的
#错误消息,但是为了简单起见
#我们假设他们提供了

user_name = request.form [name]
password = request.form [password]
user = db.find_by_name_and_password(user_name,password)

如果不是用户:
#再一次抛出一个错误不是用户友好的
#处理方式,但是这个只是一个例子
提高ValueError(提供的用户名或密码无效)

#N我们不*立即返回*响应
响应=重定向(url_for(do_that))
response.set_cookie('YourSessionCookie',user.id)
返回响应

@ app.route(/ do-that)
def do_that():
user_id = request.cookies.get('YourSessionCookie')
if user_id:
user = database.get(user_id)
如果用户:
#成功!
return render_template('do_that.html',user = user)
else:
return redirect(url_for('login'))
else:
return redirect( url_for('login'))



烘干代码



现在,您会注意到 home do_that code>方法,都与登录有关。您可以通过编写自己的装饰器来避免这种情况(请参阅 什么是装饰器 ,如果您想要了解更多关于它们的信息):

  from functools import wraps $ b $ from flask import flash 

def login_required(function_to_protect):
@wraps(function_to_protect)
def wrapper(* args,** kwargs):
user_id = request.cookies.get('YourSessionCookie')
如果user_id:
user = database.get(user_id)
如果用户:
#成功!
返回function_to_protect(* args,** kwargs)
else:
flash(Session exists,but user does not exist(havemore))
return redirect(url_for(' ('login'))
返回包装
home
do_that



 #请注意login_required需要在app.route $之前b $ b#由于修饰符是从最接近到最远
#应用的,我们不想路由然后检查登录状态

@ app.route(/)
@login_required
def home():
#对于奖励积分,我们可以*将用户
#存储在一个线程本地,所以我们不必命中
#数据库再次(和我们摆脱*这*样板)。
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 装饰器变得更加简单:

 #您必须设置会话的秘密密钥工作
#确保你保持这个秘密
app.secret_key ='现在简单的东西'
$ b $ from flask导入flash,session

def login_required(function_to_protect):
@wraps(function_to_protect)
def包装(* args,** kwargs):
user_id = session.get('user_id')
if user_id:
user = database.get(user_id)
如果用户:
#成功!
返回function_to_protect(* args,** kwargs)
else:
flash(Session exists,but user does not exist(havemore))
return redirect(url_for('登录'))
else:
flash(请登录)
返回重定向(url_for('login'))

pre
pre $ p
pre $ $ $ $ $ $ $ $ $ $ $ $ $ user = database.get(session ['user_id'])


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.

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.

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'))

解决方案

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'))

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

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)

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瓶:跟踪用户会话?如何获得会话Cookie ID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆