django9-cookie 与session简介 django操作cookie django操作session django中间件
- cookie 与session简介
- django操作cookie
- django操作session
- django中间件
1.cookie与session简介
引:
HTTP协议四大特征
1.基于请求响应
2.基于TCP/IP作用于应用层之上协议
3.无状态
4.无连接
1.互联网刚刚开始兴起的时候,所有人访问网址都是一样的数据
2.互联网的发展,像阿里,淘宝,京东等业务,服务端开始需要记住客户端的状态,个人用户的内容,隐私数据需要每个人登录自己账号,才可以查到自己的内容。由于http消息又是无状态的,所以为了让服务器记住用户的信息,就用到了会话,但是会话数据毕竟是临时的,不宜长久存放,所以会有过期时间,比较重要的数据一般会用数据库来长久保存,会话一般放些状态信息,比如你登录了没。等等
于是就产生了cookie和session,来解决此问题。
每一次会话建立都要分配一个唯一的标识,可以叫Session ID或者Session key,为了让服务器和客户端会话保持一致的状态,服务器在分配1了新会话后,会在响应消息中设置一个cookie,里面一般是加密的,客户端在发送请求的时候,会携带这个Cookie,到了服务器上面就可以验证是否是在同一个会话中进行,Cookie的过期时间和服务器session的过期时间,保存标识的Cookie,也i相应的变为无效
cookie 与session
cookie
1. 什么是cookie?
服务端返回给客户端的一组键值对,保存在客户端上,跟用户信息状态相关的数据.
缺点:存在浏览器,安全性较差,容易被拦截或者窃取
2.cookie原理
cookie值都是有服务器来产生的,浏览器收到请求后,保存到本地,下次访问服务器时,浏览器会自动携带这些键值对,以便服务器根据cookie来进行判断
Session
简述:
保存在服务端上面,基于web服务器,用于保持状态的的方法。
1.django默认的session失效时间是14天
session其实分为客户端Session和服务器端Session。
当用户首次与Web服务器建立连接的时候,服务器会给用户分发一个 SessionID作为标识。SessionID是一个由24个字符组成的随机字符串。用户每次提交页面,浏览器都会把这个SessionID包含在 HTTP头中提交给Web服务器,这样Web服务器就能区分当前请求页面的是哪一个客户端。这个SessionID就是保存在客户端的,属于客户端Session。
其实客户端Session默认是以cookie的形式来存储的,所以当用户禁用了cookie的话,服务器端就得不到SessionID。这时我们可以使用url的方式来存储客户端Session。也就是将SessionID直接写在了url中,当然这种方法不常用。
流程
1.当用户登录之后,生成一个字典{key:value},将字典存入session中,key是自动生成的一段字符串,返回cookie,value是一个自定义的格式字典
2.在1步骤生成的字value自定义格式来存储用户的信息,如user信息,iflogin等
3.当我们在django中,用到jason
session和cookie的关系
session的工作需要依赖于cookie,就算目前所有能够识别用户身份的网址,也需要使用cookie(客户端浏览器也有权拒绝保存cookie)
禁用cookie
2.django操作cookie
如果想让客户端浏览器保存cookie 需要httpResponse对象调用方法
httpRsepose三板斧
return HttpResponse()
return render()
return redirct()
return JsonResponse()
设置cookie需要变形
----------------------------------------
obj = HttpResponse()
obj.cookie的方法
return obj
---------------------------------------
obj = render()
obj = render()
obj.cookie的方法
--------------------------------------
obj = redirct()
obj.操作cookie的方法
return obj
----------------------------------------
obj = JsonResponse()
obj.操作cookie的方法
return obj
1.设置cookie
参数: .set_cookie(name,'')
括号内更多使用参数
如何设置cookie
路由层url.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('setCookie/',views.setCookie),
views.py
from django.shortcuts import render, HttpResponse, redirect
# Create your views here.
# set cookie的方法
def setCookie(request):
obj = HttpResponse('我已经设置了cookie值')
# 让浏览器保存cookie数据
obj.set_cookie('name', '12345678')
return obj
key, 键
-------------
value='', 值
--------------
max_age=None, 超时时间
----------------------
expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
-------------------------------
path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的
----------------------
cookie可以被任何url的页面访问
-------------------------
domain=None, Cookie生效的域名
---------------------------
secure=False, https传输
---------------------------
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
cookie设置展示效果
案例:页面登录(cookie)
1.登录设置cookie
2.多个视图函数都需要校验用户是否登录
装饰器
3.如何记住用户登录之前想要访问的页面 用户登录成功之后自动跳转
场景1:用户访问了其他需要登录才可以访问的页面 如何跳转>>>:想要访问的
场景2:用户直接访问的登录页面 如何跳转>>>:网址首页
代码展示
1.路由层 url.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('home/',views.home),
path('index/',views.index),
path('login/',views.login),
]
2.视图层 views.py
from django.shortcuts import render, HttpResponse, redirect
# Create your views here.
#装饰器
def login_auth(func_name):
def inner(request, *args, **kwargs):
if request.COOKIES.get('name'):
res = func_name(request, *args, **kwargs)
return res
else:
target_path = request.path_info
return redirect(f'/login/?next={target_path}')
return inner
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'lzl' and password == '123':
target_path = request.GET.get('next')
if target_path:
obj = redirect(target_path) # 如果target_path 有值则调转到用户想访问的页面
else:
obj = redirect('/home/') # 没有则跳转到home首页
obj.set_cookie('name', '33333', max_age=30) # 这个obj当然是redirct(属于httpResponse)然后点调用的
return obj
return render(request, 'login.html')
@login_auth
def home(request):
return HttpResponse('home页面只有登录才能看┗|`O′|┛ 嗷~~')
@login_auth
def index(request):
return HttpResponse('index页面只有登录才能查看')
@login_auth
def func(request):
return HttpResponse('func页面 只有登录的用户才可以查看')
模型层 template
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" method="post">
<p>username:
<input type="text" name="username">
</p>
<p>passowrd:
<input type="text" name="password">
</p>
<input type="submit" value="登录">
</form>
</body>
</html>
页面效果展示
2.删除cookie
.delete_cookie("user")
eg:
def logout(request):
rep = redirect("/login/")
rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值
return rep
3.django操作session
请求来之后服务端产生随机字符串并发送给客户端保存 服务端存储随机字符串与用户信息的对应关系 之后客户端携带随机字符串 服务自动校验
session方法
- 获取,设置,删除session中数据
#获取
1.自动从请求中回去sessionid对应的随机字符串
2.拿着随机字符串去django_session中匹配数据
3.如果匹配上还会自动解密数据并展示
request.session['k1']
request.session.get['k1',None]
#设置
request.session['k1'] = 123
request.session.setdefault('k1',123) #存在则不设置
#删除
del request.session['k1']
2.所有键,值,键值对
#键
request.session.keys()
#值
request.session.values()
request.session.items()
request.session.iterkey()
3.会话sesssion的key
request.session.session_key
4.将所有Session失效日期小于当前日期的数据删除[常用]
request.session.clear_expired()
5.检查会话session的key在数据库中是否存在
request.session.exist("session_key")
6.删除当前会话数据并保持会话的cookie
request.session.flush()
这里确保前面的会话数据不可以被用户的浏览器访问
例如
django.contrib.auth.logout() 函数中就会调用它
request.session.delete()
#删除当前会话数据并删除会话的cookie
7.设置会话session和cookie的超时时间
request.session.set_expiry(value)
如果value是整数,session会在秒数后失效
如果value是datatime或者timedelta,session就会在这个时间后失效
如果value是0,用户关闭浏览器就会失效
如果value是None,session会依赖全局session 失效策略
1.设置session
视图层views.py
from django.shortcuts import render, HttpResponse, redirect
# Create your views here.
def set_session(request):
request.session['name'] = 'lzl'
return HttpResponse('设置session')
# 获取session
def get_session(request):
print(request.session.get('name'))
return HttpResponse('获取session')
def get_md(request):
print('from get_md')
def render():
return HttpResponse("哈哈哈")
obj = HttpResponse('嘿嘿嘿')
obj.render = render
return obj
路由层urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('set_session/',views.set_session),
path('get_session/',views.get_session),
path('get_md/',views.get_md),
]
下图报错 session需要存储服务端中数据库
解决:
pycharm -tools->run manage.py Task
> makemigration
->migrate
以上只是单个方法简单展示
案例:页面登录(session)
视图层 views.py
from django.shortcuts import render, HttpResponse, redirect
from functools import wraps
# Create your views here.
def check_login(func):
@wraps(func)
def inner(request, *args, **kwargs):
next_url = request.get_full_path()
if request.session.get("user"):
return func(request, *args, **kwargs)
else:
return redirect("/login/?next={}".format(next_url))
return inner
def login(request):
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd")
if user == "lzl" and pwd == "1234":
# 设置session
request.session['user'] = user
# 获取跳到登录页面之前的URL
next_url = request.GET.get("next")
print(next_url)
# 如果有则跳转回登录前访问的那个页面
if next_url:
return redirect(next_url)
else:
return redirect("/index/")
return render(request, "login.html")
@check_login
def logout(request):
# s删除所有当前请求相关的session
return redirect("/login/")
@check_login
def index(request):
current_user = request.session.get("user", None)
return render(request, "index.html", {"user": current_user})
路由层urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/',views.login),
path('logout/',views.logout),
path('index/',views.index),
]
模板层templates
#login.html
-------------------------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" method="post">
<p>username:
<input type="text" name="user">
</p>
<p>passowrd:
<input type="text" name="pwd">
</p>
<input type="submit" value="登录">
</form>
</body>
</html>
-----------------index.html--------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>session</title>
</head>
<body>
<h1>当你看到此页面的时候,您已登录成功</h1>
</body>
</html>
效果展示
Django中的session配置
Django默认的Session,内部提供了五种类型的session供开发者使用
1.数据库
2.缓存数据库
3.文件
4.缓存+数据库
5.加密
1.数据库session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' #引擎默认
2.缓存session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' #引擎
SESSION_CAACHE_ALLAS = 'DEFAULT' #使用缓存别名
3.文件session
SESSION_ENGINE = 'django.contrib.session.backends.file' #引擎
SESSION_FILE_PATH = None #缓存文件路径,如果为None,则使用temp
4.缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cache_db' #引擎
5.加密cookie_session
SESSION_ENGINE = 'django.contrib.session.backends.sined_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,默认修改之后才保存(默认)
4.django中间件
django中间件类似于django的门户,所有的请求和响应都走中间件
django默认自带七个中间件,每个中间件都有各自负责的功能
#settings配置 7个
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
django中间件除了默认的之外,还支持自定义中间件(无限)
django中间件使用场景
1.全局用户身份校验
2.全局用户黑名单校验
3.全局用户访问频率校验、
django自定义中间件的五个方法
process_request(self,request)【重点】
process_respone(self, request, response)【重点】
process_view (self,request,view_func,view_args,view_kwars) 【了解】
process_template_response(self,request,response) 【了解】
process_exception 【了解】
1.process_request(核心)
1.1请求来的时候会按照配置文件中注册了中间件从上往下一次执行,每一个中间件里的process_request方法 没有则直接跳过
1.2该方法返回了HttpResponse对象,那么请求不会再往后执行,原路返回
2.process_responese
2.1 响应走的时候会按照配置文件中注册了的中间件,从下往上一次执行,每一个中间件里面的process_response方法,没有则直接跳过
2.2该方法两个形参request和response 并且默认情况下应该返回response
2.3 该方法也可以自己返回HttpResponse对象,相当于狸猫换太子,把原本返回的数据给替换掉
2.4【注意】如果请求的过程中,process_request方法直接返回了HttpResponse对象,那么会原地执行同级别process_response方法返回(flask框架则不同)
3.process_view
3.1 当路由匹配成功之后,执行试图函数之前,自动触发
4.process_exception
当视图函数报错之后,自动触发
5.process_template_response
当视图函数返回的数据对象中含有render属性对应,render函数才会触发
中间件操作
步骤1
1.创建一个任意名称的文件夹
2.在该文件夹内创建一个任意名称的py文件
3.在该py文件内编写中间件类
4.配置文件中注册
步骤二创建的py文件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect,render
class MyMdd1(MiddlewareMixin):
def process_request(self, request):
print('自定义中间件:from MyMdd1 process_request')
# return HttpResponse('from MyMdd1 process_request')
def process_response(self, request, response):
print('自定义中间件:from MyMdd1 process_response')
return response # response就是视图函数返回给客户端的数据
# settings
MIDDLEWARE = [
# 注册自定义中间件
'app01.mymiddleware.mymdd.MyMdd1',
'app01.mymiddleware.mymdd.MyMdd2',
]
必须要掌握的方法
- process_request
def process_request(self, request):
print('自定义中间件:from MyMdd1 process_request')
return HttpResponse('from MyMdd1 process_request')
1.请求来的时候会从上往下依次执行配置文件中注册了的中间件里面的process_request方法,如果没有则直接跳过
2.如果该方法自己返回了HttpResponse对象,那么请求不再继续往后直接返回相应的数据
- process_response
def process_response(self, request, response):
print('自定义中间件:from MyMdd1 process_response')
return response # response就是视图函数返回给客户端的数据
1.响应走的时候会从下往上依次执行配置文件中注册了的中间件里面的process_response方法,如果没有则直接跳过
2.如果该方法自己返回了HttpResponse对象,那么响应会替换成该HttpResponse对象数据,而不再是视图函数想要返回给客户端的数据
PS:如果process_request返回了HttpResponse对象,那么会从当前位置从下往上执行每一个process_response。
需要了解的方法
- process_view
def process_view(self,request,view_func, view_args, view_kwargs):
# print('view_func',view_func) # 即将要执行的视图函数名
# print('view_args',view_args) # 传给视图函数的位置参数
# print('view_kwargs',view_kwargs) # 传给视图函数的关键字参数
print('自定义中间件:from MyMdd2 process_view')
路由匹配成功之后执行视图函数之前从上往下执行配置文件中注册了的中间件里面的process_view方法
- process_template_response
def process_template_response(self,request,response):
print('自定义中间件:from MyMdd2 process_template_response')
return response
视图函数执行完毕之后返回的对象中含有render属性对应一个render方法,则会从下往上执行配置文件中注册了的中间件里面的process_template_response方法
- process_exception
def process_exception(self,request,exception):
print(exception)
print('自定义中间件:from MyMdd2 process_exception')
视图函数执行过程中报错并在返回响应的时候会从下往上执行配置文件中注册了的中间件里面的process_exception