zoukankan      html  css  js  c++  java
  • flask设置cookie,设置session,模拟用户认证、模拟管理后台admin、模拟用户logout --

    设置cookie

    HTTP协议是无状态的,在一次请求响应结束后,服务器不会留下关于客户端状态的信息。但是对于某些web程序来说,客户端的信息有必要被记住,比如用户的登录状态,这样就可以根据用户的状态来返回不同的响应。为了解决这个问题就有cookie技术 。cookie技术通过在请求和响应报文中添加cookie数据来保存客户端的状态信息。

    cookie值web服务器为了存储用户信息而保存在浏览器的文本数据。浏览器在一定时间内保存它,在下一次请求服务器时会附带这个cookie数据。cookie通常被用来进行用户的会话管理(登录状态),保存用户的个性化信息(比如语言设置,视频上次播放的位置,网站主题选项等)以及记录和手机用户浏览数据以来分析用户行为等。

    在Flask中,如果想要在响应中加一个cookie,可以用Response类型的set_cookie()方法。要用这个方法,需要先使用make_response()方法手动生成一个响应对象,传入响应主体作为参数。这个响应对象默认实例化内置的Response类

    Response类型的常用属性和方法:

    set_cookie()方法支持多个参数来设置cookie的选项:

    在response中设置cookie

    set_cookie视图用来设置cookie,它会把URL中的name变量的值设置到名为name1的cookie里

    set_cookie视图会在生成的的报文首部中创建一个Set_Cookie字段,

    即”Set-Cookie:  name1=xiaxiaoxu; Path=/”

    from flask import Flask,make_response,redirect
    @app.route('/hello/<name>')
    def hello(name):
        return '<h1>Hello, %s !</hi>' %name

    @app.route('/set/<name>')
    def set_cookie(name):
    #url_for()方法的第一个参数是视图函数名,第二个参数是该函数需要的参数
        response = make_response(redirect(url_for('hello', name = 'xiaxiaoxu')))
        #把url中name变量的值添加到cookie中name属性中
        response.set_cookie('name1',name)
        return response
     


    if __name__ == '__main__':
        app.run(debug = True)

    结果:

    在浏览器的cookie中,可以看到多了一个名为name1的cookie,它的值是”xiaxiaoxu”。

    这个cookie会在关闭浏览器时过期。

    第一个请求的响应中设置了cookie

    当浏览器保存了服务器端设置的cookie后,当浏览器再次发送到该服务器的请求会自动携带设置的cookie信息,cookie的内容存储在请求首部的cookie字段中

    第二个请求的请求中有携带cookie信息

     

    Flask中,cookie可以通过请求对象的cookies属性读取。

    我们修改一下hello视图函数,如果没有从查询参数中获取到name的值,就从cookies中寻找

    @app.route('/')
    @app.route('/hello')
    def hello():
        name = request.args.get('name')
        if name is None:
            name = request.cookies.get('name','Human')#从cookie中获取name值
       
    return '<h1>Hello, %s</hi>' % name


    @app.route('/set/<name>')
    def set_cookie(name):
        response = make_response(redirect(url_for('hello',name = name)))
        response.set_cookie('name1',name)
        return response

    if __name__ == '__main__':
        app.run(debug = True)

    结果:

    浏览器中 输入…/set/xiaxiaoxu

    重定向后:地址是…/hello?name=xiaxiaoxu

    这里的?后的参数是通过redirect(url_for('hello',name = name)这句生成的,因为hello()视图函数没有提供参数,所以这里直接把name=name这句加到了url后面

    浏览器中输入127.0.0.1:5000/

    此时name的值为空,那么name从cookies里面取值,取到一个默认值Human

    session:即安全的cookie,就是把cookie数据进行了加密

    session的作用

    session在web程序中发挥很大的作用,其中最重要的功能是存储用户的认证信息。我们先来看看基于浏览器的用户认证是如何实现的。当我们使用浏览器登录某个社交网站时,会在登录表单中填写用户名和密码,单击登录按钮后,这会向服务器发送一个包含认证数据的请求。服务器接收请求后会查找对应账户,然后验证密码是否匹配,

    如果匹配,就在返回的响应中设置一个cookie,比如,”login_user: sam”

    响应被浏览器接收后,cookie会被保存在浏览器中。当用户再次想这个服务器发送请求时,根据请求附带的cookie字段中的内容,服务器上的程序就可以判断用户的认证状态,并识别出用户。

    Flask 用session对象用来加密cookie数据

    但是会带来用一个问题,在浏览器中手动添加和修改cookie是很容易的事,仅仅通过浏览器插件就可以实现。所以,如果直接把认证信息以明文的方式存储在cookie里,那么恶意用户就可以通过伪造cookie的内容来获得对网站的权限,冒用别人的账户。为了避免这个问题,我们需要对敏感的cookie内容进行加密。方便的是,Flask提供了session对象用来将cookie数据加密储存。

    在编程中,session指用户会话(user session),又称为会话,即服务器和客户端/浏览器之间或桌面程序和用户之间建立的交互活动。在Flask中,session对象用来加密Cookie。默认情况下,它会把数据存储在一个名为session的cookie里。

    设置程序密钥

    session通过密钥对数据进行签名以加密数据,因此,我们得先设置一个密钥。这里的秘钥就是一个具有复杂度和随机性的字符串。

    程序的秘钥可以通过Flask.secret_key属性或配置变量SECRET_KEY设置。

    如:

    app.secret_key = ‘secret string’

    更安全的做法是把密钥写进系统环境变量(在命令行是用export或set命令),或者保存在.env文件中:

    SECRET_KEY = secret string

    然后在程序中用os模块提供的getenv()方法获取:

    import os

    app.secret_key = os.getenv(‘SECRET_KEY’, ‘secret  string’)

    在getenv()方法中的第二个参数是作为没有获取到环境变量时使用的默认值。

    模拟用户认证:

    使用session模拟用户的认证功能,下面代码是是登录的login视图

    session对象可以像字典一样操作,我们向session中添加一个名为logged_in的cookie,值为True,表示用户已认证。

    当我们使用session对象添加cookie时,数据会使用程序的密钥对其进行签名,加密后的数据存储在一块名为session的cookie里

    from flask import redirect, session, url_for
    import os
    app.secret_key = os.getenv('SECRET_KEY','secret string')


    @app.route('/login')
    def login():
        session['logged_in'] = True #写入session
       
    return redirect(url_for('hello'))

    @app.route('/')
    @app.route('/hello')
    def hello():
        name = request.args.get('name')
        if name is None:
            name = request.cookies.get('name','Human')#从cookie中获取name值
       
    return '<h1>Hello, %s</hi>' % name

    if __name__ == '__main__':
        app.run(debug = True)

    结果:

    查看cookie页面,可以看到session的值是加密处理cookie后的值。使用session对象存储的cookie,用户可以看到其加密后的值,但不能修改。因为session中的内容使用密钥进行签名加密,一旦数据被修改,签名的值也会变化,这样在读取时,就会验证失败,对应的session值也会随之失效。

    所以,除非用户知道密钥,否则无法对session cookie的值进行修改

    第一次请求,在响应中设置了session

    重定向后的请求数据:第二次请求时,会在请求头中加入session的信息

    支持用户登录后,就可以根据用户的认证状态分别显示不同的内容,在login视图的最后,重定向到hello视图,我们修改一下hello视图,判断一下session中的认证状态,区分开处理

    session中的数据可以像字典一样通过键读取,在这里只判断一下session中是否包含loggedd_in键,如果有则表示用户已经登录,在响应中加一行[Authenticated],否则显示[Not authenticated]

    如果访问127.0.0.1:5000/login,就会登入当前用户,session中就会存储logged_in的信息,重定向到127.0.01:5000/hello后你会发现加载后的页面显示一行”[Authenticated]”,表示用户已经通过认证

    from flask import redirect, session, url_for
    import os
    app.secret_key = os.getenv('SECRET_KEY','secret string')


    @app.route('/login')
    def login():
        session['logged_in'] = True #写入session
       
    return redirect(url_for('hello'))

    @app.route('/')
    @app.route('/hello')
    def hello():
        name = request.args.get('name')
        if name is None:
            name = request.cookies.get('name','xiaxiaoxu')#从cookie中获取name值
           
    response = '<h1>Hello, %s</h1>' % name
            #根据用户认证状态返回不同内容
           
    if 'logged_in' in session:
                response += '<p>[Authenticated]</p>'
           
    else:
                response += '[Not Authenticated]'
       
    return response

    if __name__ == '__main__':
        app.run(debug = True)

    结果:

     

    模拟管理后台admin的视图

    from flask import session, abort
    import os
    app.secret_key = os.getenv('SECRET_KEY','secret string')


    @app.route('/login')
    def login():
        session['logged_in'] = True #写入session
       
    return redirect(url_for('hello'))

    @app.route('/admin')
    def admin():
        if 'logged_in' not in session:
            abort(403)
        return 'welcom to admin page'


    if __name__ == '__main__':
        app.run(debug = True)

    结果:

    没有存储登录cookie的情况下直接访问admin

    会提示403

    登录127.0.0.1:5000/login,写入session后,再次访问admin

    此时session里已经存储了logged_in cookie信息,所以可以访问

    模拟用户退出登录logout视图

    已登录用户的退出,对应的操作就是它代表用户认证的logged_in cookie删除,这样用户的登录状态就失效了,通过session对象的pop方法实现:

    @app.route('/logout')
    def logout():
        if 'logged_in' in session:
            session.pop('logged_in')
        return redirect(url_for('hello'))

    结果:

    在登录状态下,直接访问127.0.0.1:5000/logout

    在logout视图中,清楚了session的logged_in信息,然后重定向到hello视图

    重定向后的/hello页面的认证状态信息会变为[Not authenticatedd]

     

    默认情况下,session cookie会在用户关闭浏览器时删除。通过将session.permanent属性设为True可以将session的有效期延长为Flask.permanent_session_lifetime属性值对应的datetime.timedelta对象,也可通过配置变量PERMANENT_SESSION_LIFETIME设置,默认为31天

    尽管session对象会对cookie进行签名并加密,但这种方式仅能够确保session的内容不会被篡改,加密后的数据借助工具仍然可以轻易读取(即使不知道秘钥)。因此,绝对不能再session中存储敏感信息,比如用户密码。

  • 相关阅读:
    一个接口的性能问题定位和分析过程
    HTTP请求全过程(很全面)
    Linux中查看物理CPU个数、核数、逻辑CPU个数
    linux查看文件大小
    ping不通判断系统是否开机
    ping不通判断系统是否开机
    linux压缩解压文件命令
    python连接redis集群,添加数据
    初学python
    企业级BI为什么这么难做?
  • 原文地址:https://www.cnblogs.com/xiaxiaoxu/p/10392720.html
Copyright © 2011-2022 走看看