Django---cookie和session操作,CBV添加装饰器,中间件,csrf请求和解决策略

django操作cookie补充


加密盐

set_signed_cookie(key,value,salt='加密盐')
# 会在value后面产生一个字符串eg:1ntTFz:bFkwr34ztzsHQLU1qYp

后台控制过期时间

set_signed_cookie(key,value,max_age=超时时间:默认是秒数)
# expires:专门针对IE浏览器设置超时时间

删除Cookie

# HttpResponse对象.delete_cookie(key) 
def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
    return rep

django操作session


设置

request.session['key'] = value  # 可以设置多组

获取

request.session.get('key')  # 可以获取多组

服务端保存用户相关状态信息,返回给客户端随机字符串。针对保存django需要一张表来处理,就是django数据库迁移命令会产生一堆默认的表中的django_session表。里面只有三个字段(session_key,session_data,expire_date)。

设置session内部发生的事情:

  1. 产生一个随机字符串
  2. 表中存储随机字符串与加密数据的对应关系
  3. 并将产生的随机字符串也给客户端发送一份并让其保存
  4. sessionid:随机字符串

获取session内部发送的事情:

  1. 自动获取客户端请求中的随机字符串
  2. 自动去存储session数据的表中比对
  3. 如果比对成功自动获取并'解密处理'

ps:django默认的session失效时间是14天。

session补充

获取产生的随机字符串

request.session.session_key

只删客户端

request.session.delete()

服务端和客户端都删

request.session.flush()

设置超时时间

request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。

针对session数据的存储位置,有五种方案:

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'   # 引擎

CBV添加装饰器


想要在CBV上添加装饰器,我们则需要借助于一个专门的装饰器模块来实现。

from django.utils.decorators import method_decorator

方式1:直接在类中的某个方法上添加

class MyLoginView(views.View):
    @method_decorator(login_auth)
    def get(self, request):
        return HttpResponse("from CBV get view")

方式2:直接在类名上添加并指定

@method_decorator(login_auth, name='get')
class MyLoginView(views.View):
    def get(self, request):
        return HttpResponse("from CBV get view")

方式3:重写dispatch方法并添加作用于类中所有的方法

class MyLoginView(views.View):
    @method_decorator(login_auth)
    def dispatch(self, request, *args, **kwargs):
        super().dispatch(request,*args,**kwargs)

django中间件


django请求生命周期流程图

img

什么是中间件?

官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子。说的直白一点中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定的时间去执行这些方法。

我们一直都在使用中间件,只是没有注意到而已,打开Django项目的Settings.py文件,看到下图的MIDDLEWARE配置项。

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中间件的使用场景:只要是全局相关的功能都可以在中间件中编写。eg:用户黑名单校验、用户访问频率校验、网站全局用户身份校验。

自定义中间件


jango不单有七个中间件并且每个都有很多功能和方法,除此之外django还支持自定义中间件并提供五个可以自定义的方法。

process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

操作

  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

csrf跨站请求伪造和解决策略


前戏

钓鱼网站:一个模仿正规网站的网址 诱骗用户在该网站上做本应该在正规网站上做的操作,从而获取到该用户在正规网站上的数据甚至是财产。eg:假设我们需要登录网页完成转账操作,我们不小心登录到了钓鱼网站,填写了账户,密码,对方账户等信息,点击转账之后我们账户的钱确实减少了,但是对方账户却变成了一个你从来不认识的人。

原理:将收款人的账号,提前写成犯罪分子的然后隐藏,暴露给用户一个没有name属性的标签写着玩。

<p>当前账户:<input type="text" name="current_user"></p>
<p>目标账户:<input type="text" ></p>  # 写着玩,没有功能
<p>目标账户:<input type="text" name="target_user" style="display: none" value="犯罪分子"></p>  # 真正转账对象,通过display: none隐藏了
<p>转账金额:<input type="text" name="money"></p>

解决策略


form表单

<form action="" method="post">
{% csrf_token %}
<p>当前账户:<input type="text" name="current_user"></p>
<p>目标账户:<input type="text" name="target_user"></p>
<p>转账金额:<input type="text" name="money"></p>
<input type="submit">
</form>

会自动产生一个input标签,用于校验。submit提交的时候会带上这个生成的input里的value值,然后会和之前后端返回的页面里的value进行比对,如果正确,这个提交请求就让它过,如果不正确就步让请求通过。

<input type="hidden" name="csrfmiddlewaretoken" value="iQOCyIe4ETIYSfVSji3SqJlt3XeEJs8pujSuiNG5aKHrKZbfzusiLQ5erZHnfpk8"> # value随机

ajax请求

方式1:页面任意位置先写{% csrf_token %} 之后获取数据

'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()

方式2:模板语法直接获取

'csrfmiddlewaretoken':{{ csrf_token }}

通用解决方案:js脚本自动处理(只能适用于ajax提交),创建一个js文件,复制下面内容,然后在页面上引入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);
    }
  }
});
posted @ 2022-05-24 22:13  早安_1207  阅读(78)  评论(0)    收藏  举报
返回顶端