python-Django框架学习-08

172 阅读10分钟

1 Django中Cookie和Session介绍

在 Django 中可以通过 HTML Form 表单实现登录注册功能,但是在这之前,我们有必要简单介绍一下 Cookie 和 Session。比如在某些场景下,在排除用户手动删除浏览器 Cookie 以及 Cookie 未过期的情况下,用户如果在某网站登录过一次,下次访问这个网站,用户不需要输入用户名和密码就可以进入网站,这就是通过 Cookie 和 Session 实现的。本节先对 Cookie 进行介绍。

1.1 Django中Cookie简述

cookie的使用方法:

大家在学习 HTTP 超文本传输协议的时候,就已经知道 HTTP 是一种无状态的传输协议,对于事务处理没有记忆能力。对于客户端浏览器发出的请求,Web 服务器无法区分是不是源自于同一个浏览器。所以,这时就需要额外的数据用于维持会话。

我们通常用来它来记录浏览器端的信息和当前连接的确认信息。Cookie 保存在客户端浏览器存储空间中并以键值对的形式进行存储,也就是说 Cookie 也是一个类似字典对象。

在 Django 服务器端来设置浏览器的 Cookie 必须通过 HttpResponse 对象来完成,那么如何通过 HttpResponse 实现 Cookie 添加、修改或者删除呢?这里提供了一些方法,如下所示:

HttpResponse.set_cookie(key="", value='', max_age=None, expires=None) #设置或者添加 Cookie

上面的参数分别表示:key、value分别表示 COOKIES 的键与值;max_age 代表 COOKIES 的存活时间,以秒为单位;expires 表示具体过期时间,当不指定 max_age 和expires 时,关闭浏览器时此数据失效。当然还有一些其他的参数,比如说 domain 用来绑定域名从而实现跨域。那么又如何删除一个 COOKIE 呢?方法如下所示:

HttpResponse.delete_cookie(key) 

实例演示,代码如下所示:

from django.http import HttpResponse
# 设置cookie
def set_cookie_view(request):
    resp = HttpResponse()
    resp.set_cookie('username', 'qiaozhi', 10000)
    return resp

# 获取cookie
def get_cookie_view(request):
    value = request.COOKIES.get('username')
    return HttpResponse('MY COOKIE is: %s' % value)

然后配置相应的路由,如下所示:

urlpatterns=[    
    path('set_cookie/',views.set_cookie_view),
    path('get_cookie/',views.get_cookie_view),]

最后访问相应的路由,地址栏输入 1270.0.0.1:8000/index/set_cookie,使用谷歌调试工具,点击 Network 找到响应头,Cookie 都是需要进行加密处理的,在这里为了方便给大家演示,没有进行加密操作。

企业微信截图_20230428165849.png

访问 1270.0.0.1:8000/index/get_cookie,可以得到 Cookie 的值,大家也可以自己尝试一下,结果如下图所示:

企业微信截图_20230428170049.png

从上述过程中,我们知道了如何在 Django 中添加 Cookie 或者对其进行取值,但是你可能会发现这个过程其实是不安全的,很容易造成 Cookie 的泄露或者被截取的风险,而且不同浏览器的版本对存储 Cookie 的数量也有限制,且 Cookie 自身也有长度限制最大不可超过 4kb,否则会被自动截断。

一般情况下为了降低 Cookie 带来的安全性问题,可以采用和 Session 一起使用的策略。那么 Session 在 Django 中又如何应用呢?在下一节我们会对 Session 展开讲解。

1.2 Session定义以及作用

我们对 Cookie 进行了介绍,并知道在绝大多数实际场景中 Cookie 和 Session 是一起使用的,那么 Session 又是怎么回事呢?在本节我们将对 Session 进行介绍。了解完 Cookie 和 Session 后,我们就可以使用 HTML Form 表单实现一套完整的注册、登录逻辑代码了。

1.2.1 Session的定义

Session 又名会话控制,它的根本作用是在服务器上开辟一段空间用于保留浏览器和服务器交互时的会话信息。它代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以是时断时续的。Session 是一种服务器端的机制,Session 对象用来存储特定用户会话所需的信息。Session 由服务端生成,并且保存在服务器端的内存或者缓存中,也可以是硬盘或数据库中。

提示:使用 Session 需要在浏览器客户端中启动 Cookie,且需要使用 Cookie 中存储 Sessionid。Sessionid 是服务器返回给浏览器的唯一标识。

1.2.2 理解Session的作用

当用户使用浏览器访问服务器的时候,服务器就会为该浏览器建立一个 Session 会话控制。在创建这个 Session 时候,服务器通过 Sessionid 来检查是否该浏览器是第一次访问。若是初次访问,则服务器会为客户端浏览器创建一个 Session 并且生成一个 Sessionid。通过 HttResponse 响应将 Sessionid 发送给浏览器,浏览器接收后会将这个具有标识性的 Sessionid 保存在 Cookie 中,再次访问的时候由 Cookie 携带着它去访问服务器。

Sessionid 本质上是一个加密的字符串,具有唯一性与不可重复性。这就相当于服务器给浏览器发放了一张令牌或者通行证,告诉浏览器下次你再访问我的时候们,拿着通行证来。这就解决了 HTTP 的无状态,无记忆的问题,当再次访问服务器时就可以实现用户的免登录了。Session 的典型应用场景分别是:1. 判断用户是否登录;2. 实现商城的购物车的功能。

提示:不同的浏览器在服务端都有独立的 Session,它们与请求者之间是一一对应的关系。

1.3 Django中Session的使用

在 Django 的 settings.py 配置文件中,找到 INSTALLED_APPS 的列表并启用 Session 应用,同时在 MIDDLEWARE_CLASSES 中启用 SessionMiddleware 中间件。默认情况下上述两者都是开启状态。

1.3.1 Session的基本操作

Session可以用类似于字典的方式进行操作,并且Session只能够存储序列化的数据,例如字典或者列表等。

下面我们介绍 Session 的一些常规操作,如下所示:

#保存session的值到服务器
request.session['KEY'] = VALUE

#获取session的值
VALUE = request.session['KEY']
VALUE = request.session.get('KEY', 缺省值)

#删除session的值
del request.session['KEY']
request.session.flush()#删除所有session

1.3.2 Session在settings.py中的配置

如果想配置 Sessionid 在 Cookie 是中保存的生命周期,即当过期后,服务器会重新给浏览器发送 Sessionid ,可以使用如下的方式进行设置:

#默认值2周的时间
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2

同样也可以设置只要浏览器关闭时 Session 就会失效,它的模认值是 False,即表示不开启。

#开启关掉浏览器立即失效模式
SESSION_EXPIRE_AT_BROWSER_CLOSE = True

1.4 Cookie和Session的区别

通过这两节的内容,我们介绍了 Cookie 和 Session,下面我们进行一下总结,帮助大家更好的理解这两种状态保持机制。我们从它们的不同点着手开始分析。

  • 存储位置与存储方式不同

    • 它们各自的存放位置不同 Cookie 保存在客户端,而 Session 保存在服务端。
  • 安全性两者不同

    • 我们从安全角度进行考虑,Cookie 是存储在客户端浏览器中的,所以对于用户是可见的。利用一些脚本可以轻松获得浏览器中的所有 Cookie,从而带来安全隐患,所以对于敏感信息不要写在 Cookie 中,如用户的账号密码等,而 Session 是存储在服务器上的,不存在敏感信息泄露的问题。
  • 对于服务器压力不同

    • 最后对服务器造成的压力不同,Session 是保管在服务器端的,每个用户都会创建一个独立的 Session。如果此时发请求的客户端很多,也就是说平法访问的数量较多,那么此时就会产生许多的 Session,也将占用计算机大量内存空间。但是对于 Cookie 来说就无须担心,因为它保管在浏览器中,不占用服务器资源。所以针对这种情景应该选用 Cookie。
    • 对于 Cookie 和 Session 这两种机制,大家一定要熟悉它们,这是作为一名后端开发工程师必备的知识,在面试中也经常被面试官问起。如果你足够感兴趣,也可以再深加钻研。

2 Django HTML表单实现用户登录退出

如何使用 Django 实现用户的登录以及退出功能,希望大家通过这两节内容的学习,学会总结思路,把这个开发功能的过程反复练习,这样才能够更好的理解 Django 框架,而且在以后 Web 开发的道路上也会对自己大有裨益。

2.1 HTML表单实现用户的登录

  • HTML表单编写前端页面

    可以新建一个app(应用)

    在templates\user 目录下新建 login.html 文件。并在其中编写如下代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录页</title>
        <style>
                   #pwd input{
               margin-left:23px
            }
        </style>
    </head>
    <body>
    <form action="/user/login/" method="post">
    <!--传统的html登录表单-->
        <p>
            用户名: <input type="text" name="username" value="{{ username }}">
            <span> {{ error }}</span>
        </p>
        <p id=pwd> 
            密码: <input type="text" name="password" value="{{ password }}">
        </p>
        <p>
            记住用户名: <input type="checkbox" name="isSaved">
        </p>
        <p>
            <input type="submit" value="登录">
        </p>
    </form>
    </body>
    </html>
    

    上述代码理解起来非常的通俗易懂,但是不难发现我们在其中新增了一个记住用户名的小功能,没错它就是通过 Cookies 实现的。

  • 编写视图函数

    在 user\views.py 中编写视图层用户登录逻辑代码,如下所示:

    #用户的登录逻辑处理
    def login_view(request):
        #处理GET请求
        if request.method == 'GET':
            #1, 首先检查session,判断用户是否第一次登录,如果不是,则直接重定向到首页
            if 'username' in request.session:  #request.session 类字典对象
                return HttpResponseRedirect('/index/allbook')
            #2, 然后检查cookie,是否保存了用户登录信息
            if 'username' in request.COOKIES:
                #若存在则赋值回session,并重定向到首页
                request.session['username'] = request.COOKIES['username']
                return HttpResponseRedirect('/index/allbook')
            #不存在则重定向登录页,让用户登录
            return render(request, 'user/login.html')
        # 处理POST请求
        elif request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            m = hashlib.md5()
            m.update(password.encode())
            password_m = m.hexdigest()
            #判断输入是否其中一项为空或者格式不正确
            if not username or not password:
                error = '你输入的用户名或者密码错误 !'
                return render(request, 'user/login.html', locals())
            #若输入没有问题则进入数据比对阶段,看看已经注册的用户中是否存在该用户
            users = User.objects.filter(username=username, password=password_m)
            # 由于使用了filter, 所以返回值user是一个数组,但是也要考虑其为空的状态,即没有查到该用户
            if not users:
                error = '用户不存在或用户密码输入错误!!'
                return render(request, 'user/login.html', locals())
            # 返回值是个数组,并且用户名具备唯一索引,当前用户是该数组中第一个元素
            users = users[0]
            request.session['username'] = username
            response = HttpResponseRedirect('/index/allbook')
            #检查post 提交的所有键中是否存在 isSaved 键
            if 'isSaved' in request.POST.keys():
                #若存在则说明用户选择了记住用户名功能,执行以下语句设置cookie的过期时间
                response.set_cookie('username', username, 60*60*24*7)
            return response
    

    完成视图层代码后,记得要配置路由映射关系,如下所示:

    from django.urls import path
    from user import views
    urlpatterns=[
        # path('reg/',views.reg_view),
        path('login/',views.login_view)
    ]
    

2.2 实现用户的退出功能

用户的退出功能相对来说要简单的多,通过下面代码就可以实现:

def logout_view(request):
    #实现退出功能
    #删除session
    if 'username' in request.session:
        del request.session['username']
    resp = HttpResponseRedirect('/user/index')
    #删除cookie
    if 'username' in request.COOKIES:
        resp.delete_cookie('username')
    return resp
#编写视图函数映射关系
urlpatterns = [
    #http://127.0.0.1:8000/user/logout
    path('logout/', views.logout_view)
]

大家可以自行编写一个简单的网站首页,我们知道退出功能的 button 都会显示在首页边角位置,所以只需要将退出功能的 url 关联到 标签的 href 属性即可实现点击退出的功能了。