Bootstrap

Django-cookie,session

Cookie简介

Cookie,有时也用Cookies,是指web程序为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密),一般是以键值对的形式存在,Cookie具有不可跨域名性

Cookie是http协议中定义在 header 中的字段

Cookie解决无状态问题原理

客户端访问服务端,服务端生成一个有限时间的cookie给客户端,cookie保存在客户端本地浏览器,下次进行访问的时候,客户端就会携带cookie访问服务端,服务端可以通过cookie辨别客户端用户


Cookie的使用

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.


# 体验了一下报错:The view createCookie_app.views.cookie_index didn't return an HttpResponse object. It returned None instead.
def cookie_index(request):
    return HttpResponse("设置cookie").set_cookie('name', 'root')

# 先用这种
def cookie_index1(request):
    resp = HttpResponse("设置cookie")
    resp.set_cookie('name', 'root')
    return resp


def cookie_get(request):
    print(request.COOKIES)
    return HttpResponse('获取cookie:%s' % request.COOKIES['name'])

Cookie的免登录设置

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


# Create your views here.
from django.urls import reverse


def login(request):
    return render(request, 'login/login.html')


def do_login(request):
    resp = HttpResponse()
    # 获取请求体数据
    data = request.POST
    username = data['uname']
    password = data['pwd']
    try:
        rember = data['rember']
    except:
        rember = '0'
    print('username:', username)
    print('password:', password)
    if username == 'django' and password == '123':
        resp.content = '登录成功'
        if rember == 'rember':
            print('设置cookie')
            # 设置cookie
            resp.set_cookie('uname', username, max_age=60*60*24*3)
            resp.set_cookie('pwd', password, max_age=60*60*24*3)
        else:
            # 删除cookie
            resp.delete_cookie('uname')
            resp.delete_cookie('pwd')
        return resp
    else:
        return HttpResponseRedirect(reverse('login'), {'msg': '用户名或密码错误'})
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>登录页面</h1>
  {% csrf_token %}
  <form action="/do_login/" method="post">
     {% csrf_token %}
     用户名:<input type="text" name="uname" ><br>
     密码:<input type="password" name="pwd" ><br>
     记住我<input type="checkbox" name="rember" value="rember"><br>
    <input type="submit" value="登录"><br>
  </form>
</body>
</html>
from django.urls import path
from .views import *


urlpatterns = [
    path('login/', login, name='login'),
    path('do_login/', do_login, name='logout')
]

Session介绍

Session 对象存储特定用户会话所需的属性及配置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而且在整个用户会话中一直存在下去。(session是依赖于cookie的)

Django框架中的session管理允许存储和检索任意数据,它在服务器端存储数据并抽象cookie的发送和接收。

启用session

要应用session,必须开启session中间层,在settings.py中:

MIDDLEWARE = [
  # 启用 Session 中间层
  'django.contrib.sessions.middleware.SessionMiddleware',
]
五种session的引擎

Django中默认支持Session,其内部提供了5种类型供开发者使用:

  • 数据库
  • 缓存
  • 缓存+数据库
  • 文件
  • Cookie

五种方式的启动配置各异,但是启动完成后,在程序中的使用方式都相同:

数据库方式

SESSION_ENGINE = 'django.contrib.sessions.backends.db'  
# 数据库类型的session引擎需要开启此应用,启用 sessions 应用
INSTALLED_APPS = [
  'django.contrib.sessions',
]

缓存

速度最快,但是由于数据是保存在内存中,所以不是持久性的,服务器重启或者内存满了就会丢失数据

SESSION_ENGINE = 'django.contrib.sessions.backends.cache' 

缓存+数据库

速度次于单纯缓存方式,但是实现了持久性,每次写入高速缓存也将写入数据库,并且如果数据尚未存在于缓存中,则使用数据库

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'  

一般用以上三种,另外两种少用,cookie不推荐使用

文件

SESSION_ENGINE = 'django.contrib.sessions.backends.file' 
# 设置文件位置, 默认是 tempfile.gettempdir(),
# linux下是:/tmp
# windows下是: C:\Users\51508\AppData\Local\Temp
SESSION_FILE_PATH = 'd:\session_dir'

加密cookie

基于cookie的session,所有数据都保存在cookie中,一般情况下不建议使用这种方式

  1. cookie有长度限制,4096个字节
  2. cookie不会因为服务端的注销而无效,那么可能造成攻击者使用已经登出的cookie模仿用户继续访问网站
  3. SECRET_KEY这个配置项绝对不能泄露,否则会让攻击者可以远程执行任意代码
  4. cookie过大,会影响用户访问速度
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'

 Session的设置

django默认就会配置数据库存储session的设置,所以使用默认设置的时候需要配置好数据库信息

进行数据库的同步。数据库同步后会发现数据库中有一个django-session的表

之后进行设置的session将会存储在这张表内

创建与获取session

session = request.session

# 配置session的时间
session.set_expiry(秒)

# 设置session
session['uname'] = 'xxx'


# 获取session

uname = session.get('uname')

删除session

# 删除某个key
del request.session['has_commented']
# 从会话中删除当前会话数据并删除会话cookie
flush()
# 设置会话的到期时间
# 如果value是整数,则session将在多少秒不活动后到期
# 如果value是一个datetime或timedelta,该session将在相应的日期/时间到期
# 如果value是0,用户的会话cookie将在用户的Web浏览器关闭时到期
# 如果value是None,则会话将恢复为使用全局会话到期策略
set_expiry(value)


其他session方法

# 设置测试cookie以确定用户的浏览器是否支持cookie
set_test_cookie()
# 返回True或者False,取决于用户的浏览器是否接受测试cookie
test_cookie_worked()
# 删除测试cookie
delete_test_cookie()
# 返回此会话到期之前的秒数
# kwargs 为 `modification` 和 `expiry`,一般不指定
# modification:最后一次访问日期,默认当前时间, now
# expiry: 到期剩余秒数,默认全局配置时间
get_expiry_age(**kwargs)
# 返回此会话将过期的日期
# 参数同 get_expiry_age
get_expiry_date(**kwargs)
# 返回True或者False,取决于用户的Web浏览器关闭时用户的会话cookie是否会过期
get_expire_at_browser_close()
# 从会话存储中删除过期的会话,这是个类方法。
clear_expired()
# 在保留当前会话数据的同时创建新的会话密钥
cycle_key()
 

session的settings.py使用

# Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_NAME = "sessionid" 
# Session的cookie保存的路径(默认)
SESSION_COOKIE_PATH = "/" 
# Session的cookie保存的域名(默认)
SESSION_COOKIE_DOMAIN = None
# 是否Https传输cookie(默认)
SESSION_COOKIE_SECURE = False
# 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_HTTPONLY = True
# Session的cookie失效日期(2周)(默认)
SESSION_COOKIE_AGE = 1209600
# 是否关闭浏览器使得Session过期(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
# 是否每次请求都保存Session,默认修改之后才保存(默认)
SESSION_SAVE_EVERY_REQUEST = False  


session登录

使用了admin的后台管理系统

views.py

重定向还有模板jinja2语法好重要哟

from django.contrib import auth
from django.contrib.auth import authenticate, login
from django.shortcuts import render, redirect
from django.views import View
from django.urls import reverse
from django.http import HttpResponseRedirect
# Create your views here.

class m_login(View):
    def get(self, request):
        error_message = request.session.get('login_err')
        request.session['login_err'] = None
        return render(request, 'login.html', {'login_err':error_message})
    def post(self, request):
        username = request.POST.get('uname')
        password = request.POST.get('pwd')
        print(username)
        print(password)
        user = auth.authenticate(username=username, password=password)
        if user:
            login(request, user)  # login() 会在 session 中保存用户的ID。
            return render(request, 'index.html', {'name': username})
            # return render(request, 'index.html', {'name': username})
        else:
            request.session['login_err'] = '用户名或密码错误!'
            return redirect('session:login')

def index(request):
    # 判断用户是否登录

    # 没有登录
    return HttpResponseRedirect(reverse('session:login'))

session登出

# 判断用户是否登录,# 没有登录,则跳转到登录页面
@login_required(login_url='session:login')
def index(request):
    # 有登录正常返回首页
    return HttpResponseRedirect(reverse('session:index'))

# 退出登录
def logout(request):
    auth.logout(request)  # 清除session中的用户信息
    return HttpResponseRedirect(reverse('session:login'))

;