Django-Cookies && Session

姬歌者
2023-12-01

HTTP被设计为”⽆态”,也就是俗称“脸盲”。 这⼀次请求和下⼀次请求 之间没有任何状态保持,我们⽆法根据请求的任何⽅⾯(IP地址,⽤户代理等)来识别来⾃同⼀⼈的连续请求。实现状态保持的⽅式:在客户端或服务器端存储与会话有关的数据(客户端与服务器端的⼀次通信,就是⼀次会话)

一、Cookies

cookies 是浏览器为 Web 服务器存的⼀⼩信息。 每次浏览器从某个服务器请求页面时,都会⾃动带上以前收到的cookie。cookie保存在客户端,安全性较差,注意不要保存敏感信息

1.1、设置Cookies

HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
# 同上,不同点在于设置salt,即加盐
HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
key:cookie的名称(*)

value:cookie的值,默认是空字符

max_age:cookies的持续有效时间(以秒计),如果设置为None,cookies在浏览器关闭的时候就失效了。

expires:cookies的过期时间,格式:"Wdy,DD-Mth-YYHH:MM:SSGMT"如果设置这个参数,它将覆盖max_age。

path:cookie⽣效的路径前缀,浏览器只会把cookie回传给带有该路径的页面,这样你可以避免将cookie传给站点中的其他的应⽤。/表示根路径,根路径的cookie可以被任何url的⻚⾯访问

domain:cookie⽣效的站点。你可⽤这个参数来构造⼀个跨站cookie。如,domain=".example.com"所构造的cookie对下⾯这些站点都是可读的:www.example.com、www2.example.com。如果该参数设置为None,cookie只能由设置它的站点读取。

secure:如果设置为True,浏览器将通过HTTPS来回传cookie。

httponly:仅http传输不能使⽤js获取cookie

1.2、获取Cookies

# 获取cookie
HttpRequest.COOKIES.get(key)
# 获取加“盐”的cookie
HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='',max_age=None)

1.3、删除Cookies

# 删除cookie
HttpResponse.delete_cookie(key, path='/', domain=None)

1.4、Cookies路由保护实例

app/views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from django.urls import reverse


def check_login(func):
    def inner(request, *args, **kwargs):
        if request.COOKIES.get('username'):
            return func(request, *args, **kwargs)
        else:
            return redirect(reverse('app:login'))

    return inner


@check_login
def index(request):
    return HttpResponse(request.COOKIES.get('username') + ' is login')


def login(request):
    if request.method == 'POST':
        postData = request.POST.dict()
        postData.pop('csrfmiddlewaretoken')
        # 这里我们为了方便不在进行数据库查询,直接设置username和password
        if postData.get('username') == '123' and postData.get('password') == '123':
            res = redirect(reverse('app:index'))
            # 设置10s后过期
            res.set_cookie(key='username', value=postData.get('username'), max_age=10)
            return res
    return render(request, 'app/login.html')

app/urls.py

from django.urls import path, include
from app import views

app_name = 'app'

urlpatterns = [
    path('index/', views.index, name='index'),
    path('login/', views.login, name='login'),
]

template/app/login.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="http://127.0.0.1:8000/app/login/" method="post">
        {% csrf_token %}
        username:<input type="text" name="username">
        password:<input type="text" name="password">
        <input type="submit">
    </form>
</body>
</html>

我们运行项目可以发现,登陆以后我们可以到主界面,但是十秒钟以后刷新时就需要重新登陆了。

二、Session

cookie看似解决了HTTP(短连接、⽆状态)的会话保持问题,但把全部⽤户数据保存在客户端,存在安全隐患,于是session出现了。我们可以把关于⽤户的数据保存在服务端,在客户端cookie⾥加⼀个sessionID(随机字符串)。其⼯作流程:
(1)、当⽤户来访问服务端时,服务端会⽣成⼀个随机字符串;
(2)、当⽤户登录成功后把{sessionID:随机字符串}组织成键值对加到cookie⾥发送给⽤户;
(3)、服务器以发送给客户端cookie中的随机字符串做键,⽤户信息做值,保存⽤户信息;
(4)、再访问服务时客户端会带上sessionid,服务器根据sessionid来确认⽤户是否访问过⽹站

2.1、区别与联系

这样我们的信息就保存在了服务器中,客户端只保存了SessionID,这样很安全,但是加重了服务器的负担,每次都需要查询服务器,而且分布式中这样的方式再不同的服务器上还需要重新登录。cookie在客户端存储值有⼤⼩的限制,⼤约⼏kb,session信息存储在服务器则没有限制

Session基于Cookies实现

2.2、Session的配置

# 这个app默认是有的
INSTALLED_APPS = [
    'django.contrib.sessions',
]
# 这个中间件默认也是有的
MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
]

要使用Session必须先进行数据库的迁移

2.3、Session的设置

我们还用上一个例子来讲解Session的设置

只需要修改 views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from django.urls import reverse


def check_login(func):
    def inner(request, *args, **kwargs):
        if request.session.get('username'):
            return func(request, *args, **kwargs)
        else:
            return redirect(reverse('app:login'))

    return inner


@check_login
def index(request):
    return HttpResponse(request.session.get('username') + ' is login')


def login(request):
    if request.method == 'POST':
        postData = request.POST.dict()
        postData.pop('csrfmiddlewaretoken')
        # 这里我们为了方便不在进行数据库查询,直接设置username和password
        if postData.get('username') == '123' and postData.get('password') == '123':
            res = redirect(reverse('app:index'))
            # 我们设置session,这里注意这个方法在request中
            request.session['username'] = postData.get('username')
            return res
    return render(request, 'app/login.html')

我们监控我们提交表单的时候我们发送了什么,headers里面有Cookie

Cookie: csrftoken=SivHHihe4ppXF49toaZ0R2SxBisHyOpfwcU2cGi9K3B7JXdBIT71LAnMBHvinDFL; sessionid=epqs9x94bwy9pf8sf12d48bmg65f6s4l

我们发现我们发送了一个sessionID,至于我们保存的username已经被保存在了数据库中,这也是为什么要进行数据迁移的原因。

2.4、Session的删除

# clear 清空所有session,但不会把表中的数据删除
# flush 清空所有并删除表中数据
# logout 退出登录,清除所有并删除表中数据
# del req.session['key'] 删除某一个session值
def logout(request):
	request.session.flush()
    return redirect(reverse("App:login"))
 类似资料: