资讯专栏INFORMATION COLUMN

19.设置服务器端Session【番外】

Joyven / 727人阅读

摘要:在保存登录状态与注销功能这篇文章中,我们使用了来保存,实际上默认的功能,是客户端,与之相对的是服务器端。今天我们来实现服务器端,原理很简单,实际上在编程实现和这篇文章中我们已经做过了。现在我们用数据库来保存,并为其设置有效期。

在11.保存登录状态与注销功能这篇文章中,我们使用了session来保存username,实际上Flask默认的session功能,是客户端session(client-side session),与之相对的是服务器端session(server-side session)。简单来说,这里的客户端session是将username加密后,以cookie的形式返还给客户端,客户端后续访问网站就携带着这个cookie,服务器解密cookie得到username。也就是说,如果知道了加密方法和cookie内容,就可以解密出username,这样是不够安全的。
今天我们来实现服务器端session(server-side session),原理很简单,实际上在【python socket编程】—— 5.实现cookie和session这篇文章中我们已经做过了。现在我们用数据库来保存session,并为其设置有效期。整个逻辑是这样的:用户登录后,生成一个随机字符串,将其作为session id,与对应的username和过期时间一起存入数据库,然后将session id作为cookie返回给客户端,客户端后续访问时,携带着含有session idcookie,服务器通过cookie中的session id在数据库中检索session数据,判断登录状态。


建立一个sessions表(ORM模型)来存储session,字段如下:

class MySession(db.Model):
    __tablename__ = "sessions"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # s_id代表session id,也是后面返回给客户端的cookie
    s_id = db.Column(db.String(24), nullable=False)
    username = db.Column(db.String(64), nullable=False)
    start_time = db.Column(db.DateTime, nullable=False)
    expire_time = db.Column(db.DateTime, nullable=False)

视图函数代码如下:

@app.route("/session/", methods=["GET", "POST"])
def test_session():
    username = None
    if request.method == "GET":
        s_id = request.cookies.get("sid")
        if s_id:
            mysession = MySession.query.filter(MySession.s_id == s_id).first()
            if mysession and mysession.expire_time > datetime.now():
                    username = mysession.username
        return render_template("session.html", username=username)
    else:
        username = request.form.get("username")
        s_id = random_strings(24)
        now = datetime.now()
        expire_time = now + timedelta(seconds=10)
        mysession = MySession(s_id=s_id, username=username, start_time=now, expire_time=expire_time)
        db.session.add(mysession)
        db.session.commit()
        response = make_response(redirect(url_for("test_session")))
        response.set_cookie("sid", s_id)
        return response

我们从POST方法讲起,当用户POST一个username过来时(为了简单,session.html只有用户名没有密码),生成一个随机字符串(random_strings是自己编写的一个小函数)作为session id,然后获取现在的时间now和过期时间expire_time(为了演示方便,过期时间是10秒之后),然后将这些信息存入MySession模型中,最后使用make_response方法生成一个response对象(这个对象有set_cookie方法,这也是Flask设置cookie的常规方法),并为其设置cookieset_cookie第一个参数"sid"key,第二个参数是value(session id),之后返回response对象。当请求是GET时候,首先就会使用request.cookies.get("sid")去获取cookie中的session id,如果获取到并且还在过期时间内,则向html传入username表明当前已经登录的用户。


最后html的内容如下:




    
    Title


{% if username %}

Welcome {{ username }}

{% else %}

Username:

{% endif %}

效果展示:
未登录时:

登录后:

此时数据库中的session信息:

浏览器中的cookie内容:

过期之后浏览器仍然携带这个cookie,但刷新网页又变成未登录的状态了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41394.html

相关文章

  • PostCSS自学笔记(二)【番外篇一】

    摘要:通过配置规则和单位使用或来解决。其他关于我个人的一系列学习介绍及总结有兴趣可以参阅自学笔记一安装使用篇自学笔记二插件篇自学笔记二番外篇一自学笔记二番外篇二 利用PostCSS解决移动端REM适配问题 上一期有提到结合postcss-px2rem插件来处理移动端适配的方案,以及相关的避坑方法,之后总觉得这个解决方案问题太多,也就诞生了另一套方案运用postcss-pxtorem插件来进行...

    Harpsichord1207 评论0 收藏0
  • RxJava系列番外篇:一个RxJava解决复杂业务逻辑的案例

    摘要:之前写过一系列的文章,也承诺过会尽快有的介绍。所以这次还是给大家分享一个使用解决问题的案例,希望对大家在使用的时候有一点点启发。上述这一套复杂的业务逻辑如果使用传统编码方式将是极其复杂的。 之前写过一系列RxJava1的文章,也承诺过会尽快有RxJava2的介绍。无奈实际项目中还未真正的使用RxJava2,不敢妄动笔墨。所以这次还是给大家分享一个使用RxJava1解决问题的案例,希望对...

    EscapedDog 评论0 收藏0
  • 【面试系列】番外:关于搜狐面试

    摘要:番外关于搜狐面试结果早上十点半去的,一面之后紧接着又是一面。手写模拟的双向数据绑定手写有哪些属性总结今天的面试的考察基本上都是,难度一般。今天月份刚刚毕业,经过这次搜狐面试,已经成功拿到搜狐,现在已经成功入职。 番外:关于搜狐面试 结果 早上十点半去的,一面之后紧接着又是一面。感觉还好,应该还能继续! 问题 一面: 1.数组去重,并计算时间复杂度。找出最优解决方案。(手写代码)2.定义...

    Leck1e 评论0 收藏0

发表评论

0条评论

Joyven

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<