django中级之 cookie与session中间件

  • cookie与session
  • django中间件
  • csrf跨站请求伪造

cookie与session简介

"""
HTTP协议四大特性
	1.基于请求响应
	2.基于TCP、IP作用于应用层之上协议	
	3.无状态
		服务端无法识别客户端的状态
			1.互联网刚开始兴起的的时候 所有人访问网址都是一样的数据
				服务端无法识别客户端问题不大
			2.互联网发展 淘宝、京东、阿里
				服务端不得不想办法记住客户端的状态
				cookie与session应运而生
	4.无连接
"""
Cookie
	保存在客户端上跟用户信息(状态)相关的数据	
Session
	保存在服务端上跟用户信息(状态)相关的数据
ps:session的工作需要依赖于cookie 就算是目前所有能够识别用户身份的网址也都需要使用cookie(客户端浏览器也有权拒绝保存cookie)

django操作cookie

如果想要让客户端浏览器保存cookie需要HttpResonse对象调用方法
return HttpResponse()
return render()
return redirect()
return JsonRepsonse()

设置cookie需要变形
obj = HttpResponse()
obj.操作cookie的方法
return obj

obj = render()
obj.操作cookie的方法
return obj

obj = redirect()
obj.操作cookie的方法
return obj

obj = JsonRepsonse()
obj.操作cookie的方法
return obj

1.登录设置cookie
2.多个视图函数都需要校验用户是否登录
	装饰器
3.如何记住用户登录之前想要访问的页面 用户登录成功之后自动跳转
	场景1:用户访问了其他需要登录才可以访问的页面   如何跳转>>>:想要访问的
 	场景2:用户直接访问的登录页面  如何跳转>>>:网址首页
获取网址后缀的方法:
		print(request.path)
		print(request.path_info)
		print(request.get_full_path())
		
cookie代码
无装饰器流程
1.执行未装饰的函数无需走装饰器直接判定密码是否正确
2.正确则走获取路径路径没有值所以直接跳转自定义首页

有装饰器流程
1.执行函数先走装饰器验证是否有令牌有则直接执行函数
2.没有令牌获取当前网址后缀然后跳转登陆页面进行登陆验证
3.执行登陆函数判定密码是否正确
4.密码正确之后通过GET方法获取?后携带的数据如果有数据跳转数据对应的路由没有携带数据则跳转自定义首页

# cookie装饰器
def login_auth(func):
    def inner(request, *args, **kwargs):  # 将形参request单独拎出或者使用args[0]
        if request.COOKIES.get('name'):  # 判断是否拥有令牌如果有则可以执行当前函数没有则直接返回登陆界面
            res = func(request, *args, **kwargs)
            return res
        else:
            target_path = request.path  # 获取登陆时输入的后缀
            print()
            return redirect('/login/?next=%s' % target_path)  # 如果用户没有登陆说明没有cookie直接返回登陆页面
    return inner


def login(request):
    print('1',request.GET)
    if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        print('2',request.GET)
        if name == 'jason' and pwd == '123':
            print('3', request.GET)
            target_path = request.GET.get('next')  # 登陆成功时获取后缀?后的值如果有值则跳转到?后的路径
            if target_path:
                obj = redirect(target_path)  # 有值跳转到该页面
            else:
                obj = redirect('/home/')  # 如果没有直接跳到自定义首页
            obj.set_cookie('name', '3309niubi')  # 在跳转之前需要将cookie传入客户端再跳转max_age=3秒可以设置时间
            return obj
    return render(request, 'login.html')


@login_auth  # 使用装饰器之后需要经过装饰器验证才能登陆执行函数
def index(request):
    # if request.COOKIES.get('name'):
    return HttpResponse('from index')
    # return redirect('/login/')


@login_auth
def reg(request):
    # if request.COOKIES.get('name'):
    return HttpResponse('from reg')
    # return redirect('/login/')

@login_auth
def home(request):
    return HttpResponse('首页')

django操作session

与cookie 操作一致装饰器处修改获取令牌的方法
def login_auth(func):
    def inner(request, *args, **kwargs):  # 将形参request单独拎出或者使用args[0]
        if request.session.get('name'):  # 判断是否拥有令牌如果有则可以执行当前函数没有则直接返回登陆界面
            res = func(request, *args, **kwargs)
            return res
        else:
            target_path = request.path  # 获取登陆时输入的后缀
            return redirect('/login2/?next=%s' % target_path)  # 如果用户没有登陆说明没有cookie直接返回登陆页面
    return inner
def login2(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        if name == 'jason' and pwd == '123':
            request.session['name'] = 'jason'  # 设置seesion之后直接获取路径判断
            url_path = request.GET.get('next')
            if url_path:  # 判断是否有值
                return redirect(url_path)
            else:
                return redirect('/home/')
        else:
            return HttpResponse('密码错误')
    return render(request, 'login.html')
@login_auth
def check_login(request):
    return HttpResponse('from check_login 登陆之后才能访问')
@login_auth
def home(request):
    return HttpResponse('首页')
session存储位置五种
数据库
缓存数据库
文件
缓存加数据库
加密



请求来之后服务端产生随机字符串并发送给客户端保存 服务端存储随机字符串与用户信息的对应关系 之后客户端携带随机字符串 服务自动校验
1.django默认的session失效时间14天
2.客户端会接收到键值对 键默认是sessionid值是加密的随机字符串(令牌)
request.session['name'] = 'jason'
	1.django自动产生一个随机字符串返回给客户端(对name加密)
 	2.往django_session创建数据(对jason加密)
request.session.get('name')
	1.自动从请求中回去sessionid对应的随机字符串
  	2.拿着随机字符串去django_session中匹配数据
  	3.如果匹配上还会自动解密数据并展示
 session其他操作
	# 删除当前会话的所有Session数据
    request.session.delete()
    # 删除当前的会话数据并删除会话的Cookie。
    request.session.flush() 
    # 设置会话Session和Cookie的超时时间
    request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效。
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。

django中间件

image

django中间件类似于django的门户 所有的请求来和响应走都必须经过中间件
django默认自带七个中间件 每个中间件都有各自负责的功能
django中间件除了默认的之外 还支持自定义中间件(无限)
django中间件使用场景
	全局相关的功能:
        全局用户身份校验 全局用户黑名单校验 全局用户访问频率校验
django自定义中间件中可以有五个方法
	process_request
  	process_response
 	process_view
  	process_template_response
 	process_exception

 
1.process_request
	1.请求来的时候会按照配置文件中注册了的中间件 从上往下依次执行每一个中间件里面的process_request方法 如果没有则直接跳过
 	2.该方法如果返回了HttpResonse对象 那么请求不会再往后执行 原路返回
2.process_response
	1.响应走的时候会按照配置文件中注册了的中间件 从下往上一次执行每一个中间件里面的process_response方法 没有没有则直接跳过
 	2.该方法有两个形参request和response 并且默认情况下应该返回response
  	3.该方法也可以自己返回HttpResponse对象 相当于狸猫换太子
ps:如果请求的过程中process_request方法直接反悔了HttpResponse对象那么会原地执行同级别process_response方法返回(flask则不同)
3.process_view
	当路由匹配成功之后 执行视图函数之前 自动触发
4.process_excption
	当视图函数报错之后 自动触发
5.process_template_response
	当视图函数返回的数据对象中含有render属性对应render函数才会触发

案列

继承中间件MiddlewareMixin在内部写方法

from django.utils.deprecation import MiddlewareMixin
from django.http import JsonResponse


class AuthThrottle(MiddlewareMixin):
    VISIT_RECORD = {}
    history = None

    def allow_request(self, request):
        ip = request.META.get('REMOTE_ADDR')
        import time
        ctime = time.time()
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip] = [ctime, ]
            return True
        self.history = self.VISIT_RECORD.get(ip)
        while self.history and ctime - self.history[-1] > 60:
            self.history.pop()
        if len(self.history) < 5:
            self.history.insert(0, ctime)
            return True
        else:
            return False

    def wait(self):
        import time
        ctime = time.time()
        msg = 60 - (ctime - self.history[-1])
        return msg
    import json
    def process_request(self, request):
        if self.allow_request(request):
            pass
        else:
            msg = self.wait()
            msg = str(msg)[0:2]
            return JsonResponse({"code": 101, "msg": '我在中间件拦的你啊DSB还差%s秒才能执行' % msg},json_dumps_params={'ensure_ascii':False})
posted @ 2022-09-13 00:06  懒羊羊A  阅读(38)  评论(0)    收藏  举报