cookie、session以及中间件

cookie

cookie是保存客户端浏览器上的键值对,是服务端设置在客户端浏览器上的键值对,也就意味着浏览器其实可以拒绝服务端的‘命令’,默认情况下浏览器都是直接让服务端设置键值对

设置cookie
    obj1.set_cookie()
获取cookie
    request.COOKIES.get()
删除cookie
    obj1.delete_cookie()

cookie实现登陆功能

from functools import wraps
def login_auth(func):
    @wraps(func)
    def inner( request,*args,**kwargs):
        if request.COOKIES.get('username'):
            res=func( request,*args,**kwargs)
            return res
        else:
            target_url=request.path_info    ###获取到网页的url
            return redirect('/login/?next=%s'%target_url)
    return inner

def login(request):
    if request.method=='POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'jason' and password == '123':
            old_path = request.GET.get('next')
            if old_path:
                # 保存用户登录状态
                obj = redirect(old_path)
            else:
                obj = redirect('/home/')
            obj.set_cookie('name', 'lzs')  # 让客户端浏览器 记录一个键值对
            # obj.set_cookie('name','jason',max_age=5)  # 让客户端浏览器 记录一个键值对
            return obj
    return render(request, 'login.html')


@login_auth
def home(request):
    # if request.COOKIES.get('name'):
    #     return HttpResponse('我是主页,只有登陆了才能看')
    # return redirect('/login/')
    return HttpResponse('我是主页,只要登录了才能看')

@login_auth
def index(request):
    return HttpResponse('我是index')

session

session是保存在服务器上的键值对,django session默认的过期时间是14天

设置session
    request.session['key']=value   仅仅只会在内存产生一个缓存
    1、django内部自动生成了随机的字符串
    2、在django_session表中存入数据
    3、将产生的随机的字符串发送给浏览器,让浏览器保存到cookie中
    
获取session
    request.seesion.get('key')
    1、浏览器发送cookie到django_session表中对比,是否有对应的数据
    2、拿着随机字符串去django_session表中比对,取出赋值给request.session,
       如果对不上那么request.session就是个空
        (django session表是针对浏览器的,不同的浏览器来,才会有不同额记录)
删除session
    request.session.delete()    #只删除服务端的session
    request.session.flush()      #浏览器和服务端全部删除

session也可以设置超时时间

​ request.session.set_expiry(value 多种配置)

​ 数字、0、不写、时间格式

from functools import wraps

def login_auth(func):
    @wraps(func)
    def inner(request,*args,**kwargs):
        if request.session.get('username'):
            res = func(request,*args, **kwargs)
            return res
        else:
            target_url=request.path_info
            return redirect('/login/?next=%s'%target_url)
    return inner

def login(request):
    if request.method=='POST':
        username=request.POST.get('username')
        password=request.POST.get('password')
        old_path = request.GET.get('next')
        print(old_path)
        if username=='lzs' and password=='123':
            request.session['username'] = username
            if old_path:
                obj= redirect(old_path)
            else:
                return redirect('/home/')
            # obj.set_cookie('name', 'lzs')
    return render(request,'login.html')

django中间件

  • 用户访问频率限制
  • 用户是否是黑名单
  • 所有用户登录校验
  • 只要涉及到网址全局的功能就该使用中间件
django中间件暴露给程序员五个可以自定义的方法(五个方法都是在特定的条件下自动触发的)
    1、新建一个文件夹,里面新建一个任意名称的py文件,里面写类,固定继承类
    from django.utils.deprecation import MiddlewreMixin
    class MyMiddle(MiddlewareMixin):
    2、去配置文件注册到中间件中,手写字符串的路径
    'app01.mymiddleware.myaabb.MyMiddle1' 
需要掌握:
    process_request():
        请求来的时候会从上往下经过每一个中间件里面,process_request一旦里面返回了
        HttpResponse对象那么就不再往后执行了,会执行同一级别
        eg:def process_request(self,request):
          print('我是第一个自定义中间件里面的process_request方法')
          return HttpResponse("我是第一个自定义中间件里面的HttpResponse对象返回值")  
    process_response():响应走的时候会从下往上依次经过每一个中间件里面process_response
        eg:def process_response(self,request,response):  
                # response就是要返回给用户的数据
                 print("我是第一个自定义中间件里面的process_response方法")
                  return response
了解:
    process_view:路由匹配成功之后执行视图函数之前触发
    process_exception:当视图函数出现异常(bug)的时候自动触发
    process_template_response:当视图函数执行完毕之后并且返回的对象中含有render方法的情况下才会触发
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class MyMiddle1(MiddlewareMixin):
    def process_request(self,request):
        print('我是第一个自定义中间件里面的process_request方法')
        # return HttpResponse("我是第一个自定义中间件里面的HttpResponse对象返回值")

    def process_response(self,request,response):  # response就是要返回给用户的数据
        print("我是第一个自定义中间件里面的process_response方法")
        return response

    def process_view(self,request,view_func,view_args,view_kwargs):
        print(view_func,view_args,view_kwargs)
        print('我是第一个自定义中间件里面的process_view方法')

    def process_exception(self,request,exception):
        print(exception)
        print('我是第一个自定义中间件里面的process_exception方法')

    def process_template_response(self,request,response):
        print('我是第一个自定义中间件里面的process_template_response方法')
        return response

class MyMiddle2(MiddlewareMixin):
    def process_request(self,request):
        print('我是第二个自定义中间件里面的process_request方法')

    def process_response(self, request, response):  # response就是要返回给用户的数据
        print("我是第二个自定义中间件里面的process_response方法")
        return response

    def process_view(self,request,view_func,view_args,view_kwargs):
        print(view_func,view_args,view_kwargs)
        print('我是第二个自定义中间件里面的process_view方法')

    def process_exception(self,request,exception):
        print(exception)
        print('我是第二个自定义中间件里面的process_exception方法')

    def process_template_response(self,request,response):
        print('我是第二个自定义中间件里面的process_template_response方法')
        return response

跨站请求伪造(csrf)

就类似你搭建了一个跟银行一模一样的web页面,用户在你的网站转账的时候输入用户名、密码、对方账户,银行里面的钱确实少了,但是发现收款人变了

最简单的原理:
    你写的form表单中用户的用户名、密码都会真实的提交给银行后台,但是收款账户却不是用户填的,你暴露给用户的是一个没有name属性的input框,你自己提前写好了一个带有name和value的input框

解决钓鱼网站的策略:
    只要是用户想要提交post请求的页面,在返回给用户的时候提前设置好一个随机字符串,当用户提交post请求的时候,自动先查取是否有该随机字符串,如果有正常提交,没有直接报403  
  • form表单:

    你在写的时候只需加上一个{% csrf_token %}

  • ajax:

  • 第一种自己在页面上先通过{% csrf_token %}获取随机字符串,然后利用标签查找

    data:{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},

  • 第二种:data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},

  • 第三种:拷贝js文件

    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    var csrftoken = getCookie('csrftoken');
    
    
    
    function csrfSafeMethod(method) {
      // these HTTP methods do not require CSRF protection
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    
    $.ajaxSetup({
      beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
          xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
      }
    });

视图函数

csrf_exempt:只有两种装饰的方法

 csrf_exempt  只有两种装饰的方式
     csrf_exempt         #某个视图函数不需要进行csrf校验
     csrf_protect        #某个视图函数需要进行csrf校验
    
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    from django.utils.decorators import method_decorator
   
    # 第一种
    # @method_decorator(csrf_exempt,name='dispatch')
    class MyCsrf(View):
        # 第二种
        @method_decorator(csrf_exempt)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request,*args,**kwargs)
        def get(self,request):
            return HttpResponse('hahaha')
        
            
    除了csrf_exempt之外 所有的其他装饰器 在CBV上面都有三种方式
    @method_decorator(csrf_protect,name='post')
    class MyCsrf(View):
        @method_decorator(csrf_protect)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request,*args,**kwargs)
        def get(self,request):
            return HttpResponse('hahaha')

        @method_decorator(csrf_protect)
        def post(self,request):
            return HttpResponse('post')

猜你喜欢

转载自www.cnblogs.com/lzss/p/11772158.html