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中,一般情况下不建议使用这种方式
- cookie有长度限制,4096个字节
- cookie不会因为服务端的注销而无效,那么可能造成攻击者使用已经登出的cookie模仿用户继续访问网站
- SECRET_KEY这个配置项绝对不能泄露,否则会让攻击者可以远程执行任意代码
- 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的后台管理系统
-
用django后台管理的用户登录验证
-
实现登录功能
-
django.contrib.auth
- authenticate(): https://docs.djangoproject.com/zh-hans/4.1/topics/auth/default/#authenticating-users
- login(): 使用 Django 的验证系统 | Django 文档 | Django
-
-
实现退出用户功能
- logout(): 使用 Django 的验证系统 | Django 文档 | Django
-
没登录自动跳登录页面
-
django.contrib.auth.decorators.login_required
实现 - login_required() :使用 Django 的验证系统 | Django 文档 | Django
-
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'))