目录
一.Cookie与Session的发展史
1.Cookie的发展史
2.Session的发展史
3.Cookie和Session的关系
4.总结
二.Cookie与Session详解
1.Cookie
2.Session
3.token
4.总结
三.Django操作Cookie
1.设置Cookie
2.获取Cookie
3.设置超时时间
4.注销Cookie
5.登录功能实现
(1.0)简单实现
(2.0)解决登录问题
(3.0)迭代-登录认证装饰器
四.Django操作Session
1.设置Session
2.获取Session
3.设置/获取Session多个值
4.django_session表中的session数据
5.设置过期时间
6.清空session
(1)request.session.delete():
(2)request.session.flush():
7.保存
原理剖析
案例演示
(1.0)简单的
(2.0)解决方法
(3.0)优化
Cookie和Session是用来在Web应用程序中跟踪用户会话数据的两种常用技术
Cookie和Session是Web应用程序中常用的用户会话跟踪技术
Cookie通过在客户端存储小型文本文件,并将会话标识符传递给服务器,实现会话状态的保持
Session则是在服务器端存储会话数据,通过Session ID实现对用户会话的追踪
他们的发展历程与互联网的发展紧密相关,为开发人员提供了更多的选择以保障安全性和用户体验的提升
以登录功能为例:
如果不保存用户登录状态也就意味着用户每次访问网站都需要重复的输入用户名和密码
这对用户来说体验极差
解决方法:
当用户第一次登录成功之后将用户的用户名和密码返回给浏览器,让用户浏览器保存在本地
之后访问网站的时候浏览器自动将保存在本地的用户名和密码发送给服务端,服务端获取之后自动验证,但是具有极大的安全隐患
优化:
当用户登录成功之后,服务端产生一个随机字符串(在服务端保存数据,用K:V键值对的形式),交由客户端浏览器保存
之后访问服务端时都带着随机字符串,服务端去数据库中比对是否有匹配到的随机字符串,从而获得用户信息
但是如果截取到当前随机字符串,那么就可以冒充当前用户,其实还是有极大的安全隐患
在web领域没有绝对的安全和绝对的不安全
虽然Cookie是服务端告诉客户端浏览器需要保存内容,但是客户端浏览器可以选择拒绝保存,如果禁止自动保存Cookie那么只要是需要登录的网站都没办法正常登录了
return HttpResponse()
return render()
return redirect()
obj = HttpResponse()
return obj
obj1 = render()
return obj1
obj2 = redirect()
return obj2
如果想要操作Cookie,必须进行以上变形才可以
obj = HttpResponse()
obj.set_cookie(key,value)
return obj
request.COOKIES.get(key)
obj = HttpResponse()
obj.set_cookie(key,value,max_age=5)
# 设置超时时间 5s 到期
return obj
obj = HttpResponse()
# 设置超时时间 5s 到期
obj.delete_cookie(key)
return obj
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.login),
path('home/', views.home),
]
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == "dream" and password == "521":
# 登陆成功之后,跳转到登陆成功之后才能看到的页面
return redirect('/home/')
return render(request, 'login.html')
def home(request):
return HttpResponse("登陆成功!")
问题:登录成功之后的跳转页面,不需要登录也可以直接访问到,只需要给对应的地址即可
from django.shortcuts import render, HttpResponse, redirect
# Create your views here.
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == "dream" and password == "521":
# 登陆成功之后,保存用户登陆状态
obj = redirect('/home/')
# 让浏览器记录cookie
obj.set_cookie("sign", "1314521")
'''
浏览器不单单只是帮我们保存cookie
而且在后面每次访问的时候都会带着cookie
'''
# 登陆成功之后,跳转到登陆成功之后才能看到的页面
return obj
return render(request, 'login.html')
def home(request):
# 读取携带的cookie,cookie正确登陆成功
if request.COOKIES.get("sign") == "1314521":
return HttpResponse("登陆成功!")
# 读取携带的cookie,cookie不正确跳转到登陆页面
return redirect('/login/')
用户如果没有登录的情况下想访问一个需要登录的页面,那么先跳转到登录页面,当用户输入正确的用户名和密码之后再跳转到用户之前想访问的页面去,而不是直接写死
from django.shortcuts import render, HttpResponse, redirect
# Create your views here.
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == "dream" and password == "521":
# 获取用户上一次想要访问的url
# 结果可能为空 -- 直接访问login
tag_url = request.GET.get('tag_url')
if tag_url:
obj = redirect(tag_url)
else:
# 登陆成功之后,保存用户登陆状态
obj = redirect('/home/')
# 让浏览器记录cookie
obj.set_cookie("sign", "1314521")
'''
浏览器不单单只是帮我们保存cookie
而且在后面每次访问的时候都会带着cookie
'''
# 登陆成功之后,跳转到登陆成功之后才能看到的页面
return obj
return render(request, 'login.html')
# 校验用户登录状态的装饰器
def auth_check(func):
def inner(request, *args, **kwargs):
# 获取到用户上一次想要访问的url
tag_url = request.get_full_path()
# 读取携带的cookie,cookie正确登陆成功
if request.COOKIES.get("sign") == "1314521":
res = func(request, *args, **kwargs)
return res
else:
# 读取携带的cookie,cookie不正确跳转到登陆页面
return redirect(f'/login/?next={tag_url}')
return inner
@auth_check
def home(request):
return HttpResponse("home登陆成功!")
@auth_check
def index(request):
return HttpResponse("index登陆成功!")
@auth_check
def func(request):
return HttpResponse("func登陆成功!")
Session数据是保存在服务端的,给客户端返回的是一个随机字符串
request.session['key'] = value
request.session.get('key')
- django_session表中的数据条取决于浏览器
- 同一个计算器(IP地址)上同一个浏览器只会有一条数据失效
- 同一个计算器(IP地址)上多个浏览器会有多个数据生效
- 当session过期的时候可能会出现多条数据对应一个浏览器
- 但是这些数据不会持久化存储,会被定时清理掉,可以手动清除也可以代码清除
- 目的是为了节省服务器数据库资源
# 设置session
request.session['key'] = value
# 设置过期时间
request.session.set_expiry()
只删除服务端的
该方法用于删除当前用户的Session数据,但是会保留Session的Key,这意味着Session对象本身仍然存在,但其中的数据将被清空,下次访问时,如果Session没有被重新填充则会得到一个空的Session对象
def clear_session(request):
request.session.delete()
# 其他操作或返回响应
服务端和客户端都删除
该方法用于完全删除当前用户的Session,包括Session对象的所有相关数据,下次访问时将创建一个新的空Session对象
def clear_session(request):
request.session.flush()
# 其他操作或返回响应
1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
其他公用设置项:
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
# session操作
path('set_session/', views.set_session),
def set_session(request):
request.session['sign'] = "369"
return HttpResponse("返回消息")
OperationalError at /set_session/
no such table: django_session
- 数据是保存在服务端的
- 在默认情况下操作session的时候需要Django默认的一张django_session表
- 数据库迁移命令时
- Django会默认创建很多表,其中就有Django_session表
- Django默认session的过期时间是14天
- 但是我们可以人为的修改过期时间
# session操作
path('set_session/', views.set_session),
path('get_session/', views.get_session),
def set_session(request):
request.session['sign'] = "369"
return HttpResponse("返回消息")
def get_session(request):
request.session.get("sign")
return HttpResponse("拿取成功消息")