Куки и сессии Django

Cookie — это текстовый файл, хранящийся на компьютере клиента и содержащий различную информацию для отслеживания.

Идентификация возвращающихся пользователей включает три шага:

  • Серверный скрипт отправляет браузеру набор cookie. Например: имя, возраст или идентификационный номер и т. д.
  • Браузер сохраняет эту информацию на локальном компьютере для будущего использования.
  • В следующий раз, когда браузер отправляет любой запрос веб-серверу, браузер отправляет эту информацию cookie на сервер, и сервер использует эту информацию для идентификации пользователя.

HTTP — это протокол «без сохранения состояния», что означает, что каждый раз, когда клиент получает веб-страницу, клиент открывает отдельное соединение с веб-сервером, и сервер автоматически не сохраняет никаких записей о предыдущих запросах клиента.

Однако по-прежнему существуют следующие три способа поддержания сессии между веб-клиентом и веб-сервером:

Cookies

Веб-сервер может назначить уникальный идентификатор сессии в виде cookie каждому веб-клиенту, и для последующих запросов клиента полученный cookie может использоваться для его идентификации.

В веб-разработке сессия используется для отслеживания сессии, и в основе сессии лежит технология cookie.

Синтаксис cookie в Django

Установить cookie:

rep.set_cookie(key,value,...) 
rep.set_signed_cookie(key,value,salt='加密盐',...)

Получить cookie:

request.COOKIES.get(key)

Удаление cookie:

rep =HttpResponse || render || redirect 
rep.delete_cookie(key)

Создание приложений и моделей

models.py

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)

urls.py

from django.contrib import admin
from django.urls import path
from cookie import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    path('order/', views.order)

views.py

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    username = request.POST.get("username")
    password = request.POST.get("pwd")

    user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
    print(user_obj.username)

    if not user_obj:
        return redirect("/login/")
    else:
        rep = redirect("/index/")
        rep.set_cookie("is_login", True)
        return rep
       
def index(request):
    print(request.COOKIES.get('is_login'))
    status = request.COOKIES.get('is_login') # Когда браузер отправляет очередной запрос, определите, является ли cookie, которую он несёт, cookie, установленной в ответе при успешном входе.
    if not status:
        return redirect('/login/')
    return render(request, "index.html")


def logout(request):
    rep = redirect('/login/')
    rep.delete_cookie("is_login")
    return rep # Выполнить после нажатия кнопки выхода из системы, удалить cookie, больше не сохранять состояние пользователя и перенаправить на страницу входа
   
def order(request):
    print(request.COOKIES.get('is_login'))
    status = request.COOKIES.get('is_login')
    if not status:
        return redirect('/login/')
    return render(request, "order.html")

Далее создаются три файла шаблонов: login.html, index.html, order.html.

login.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Заголовок</title> </head> <body> <h3>Вход пользователя</h3> <form action="" method="post"> {% csrf_token %} <p>Имя пользователя:<input type="text" name="username"></p> <p>Пароль:<input type="password" name="pwd"></p> <input type="submit"> </form> </body> </html>

index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Заголовок</title> </head> <body> <h2>главная страница...</h2> <a href="/logout/">Выйти</a> </body> </html>

order.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Заголовок</title> </head> <body> <h2>страница заказа...</h2> <a href="/logout/">Выйти</a> </body> </html>

Результат выполнения показан на рисунке ниже:

Сессия (пары ключ-значение, хранящиеся на стороне сервера)

Когда сервер работает, он может создавать выделенный объект сессии для каждого браузера пользователя. Поскольку сессия принадлежит исключительно браузеру пользователя, когда пользователи обращаются к веб-ресурсам сервера, они могут сохранять свои данные в своих собственных сессиях. Когда пользователи впоследствии обращаются к другим веб-ресурсам на сервере, эти другие веб-ресурсы извлекают данные из соответствующих сессий пользователей, чтобы обслуживать пользователей.

Как это работает

  • a. Сначала браузер запрашивает страницу входа.

  • b. Когда браузер вводит аккаунт и пароль для второго запроса, если ввод правильный, сервер отвечает браузеру главной страницей и cookie, ключ которого — sessionid, а значение — случайная строка, т. е. set_cookie("sessionid", random_string).

  • c. Внутри сервер сохраняет запись в таблице django.session.

    В таблице django.session есть три поля.

    • session_key: хранит случайную строку, т. е. значение, соответствующее ключу sessionid в cookie, отправленном браузеру.
    • session_data: хранит информацию пользователя, т. е. несколько записей вида request.session["key"]=value, и это шифротекст.
    • expire_date: хранит время истечения срока действия этой записи (по умолчанию 14 дней).
  • d. Когда браузер в третий раз запрашивает другие ресурсы, он передаёт cookie: {sessionid: random_string}. Сервер извлекает данные пользователя из таблицы django.session на основе случайной строки, чтобы пользователь мог их использовать (т. е. сохранение состояния).

Примечание:Таблица django.session хранит информацию о браузере, а не информацию о каждом пользователе. Поэтому запросы от нескольких пользователей, использующих один и тот же браузер, сохраняют только одну запись (последняя перезаписывает предыдущую), и только запросы из нескольких браузеров сохраняют несколько записей.

Куки компенсируют отсутствие состояния в HTTP, позволяя серверу узнать, «кто» этот человек. Однако куки хранятся в браузере в виде текста, что менее безопасно, а максимальный поддерживаемый размер составляет всего 4096 байт. Поэтому используйте куки только для идентификации разных пользователей, а приватную информацию и текст, превышающий 4096 байт, храните в соответствующей сессии.

настройки сессии:

request.session["key"] = value

Шаги выполнения:

  • a. Сгенерировать случайную строку
  • b. Сохранить случайную строку и заданные пары ключ-значение в session_key и session_data таблицы django_session.
  • c. Настройкиcookie: set_cookie("sessionid", случайная строка)Ответить браузеру

получение сессии:

request.session.get('key')

Шаги выполнения:

  • a. Получить значение ключа sessionid из куки, то есть случайную строку.
  • b. Отфильтровать запись из таблицы django_session по случайной строке.
  • c. Получить данные из поля session_data.

Удаление сессии: удалить всю запись (включая три поля session_key, session_data, expire_date):

request.session.flush()

Удалить одну из пар ключ-значение в session_data:

del request.session["key"]

Шаги выполнения:

  • a. Получить значение ключа sessionid из куки, то есть случайную строку.
  • b. Отфильтровать запись из таблицы django_session по случайной строке.
  • c. Удалить отфильтрованные записи

Пример

Создать маршрут:

urls.py

from session import views as session_views

urlpatterns = [
    path('session_login/', session_views.login),
    path('s_index/', session_views.s_index),
    path('s_logout/', session_views.s_logout),
]

Создать функцию представления:

views.py

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    username = request.POST.get("username")
    password = request.POST.get("pwd")

    user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
    print(user_obj.username)

    if not user_obj:
        return redirect("/session_login/")
    else:
        request.session['is_login'] = True
        request.session['user1'] = username
        return redirect("/s_index/")


def s_index(request):
    status = request.session.get('is_login')
    if not status:
        return redirect('/session_login/')
    return render(request, "s_index.html")


def s_logout(request):
   # del request.session["is_login"] # Удалить набор пар ключ-значение в session_data
    request.session.flush() # Удалить одну запись, включая (session_key session_data expire_date), три поля
    return redirect('/session_login/')

Файл шаблона:

s_index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Заголовок</title> </head> <body> <h2>страница session_index... {{ request.session.user1 }}</h2> <a href="/s_logout/">Выйти</a> </body> </html>

Результат выполнения показан на рисунке ниже:

Другие расширения