Loading

django操作cookie补充、Django操作session、CBV添加装饰器、django中间件、csrf跨站请求伪造

django操作cookie补充

就是在设置cookie的时候不使用set_cookie了,而是使用下面这个:
	参数:
        default: 默认值
        salt: 加密盐
        max_age: 后台控制过期时间
    set_signed_cookie(key,value,salt='加密盐')
    set_signed_cookie(key,value,max_age=超时时间:默认是秒数)
    expires:专门针对IE浏览器设置超时时间

参数

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

HttpResponse对象.delete_cookie(key) 
eg:
    def logout(request):
        res = redirect('/login/')
        res.delete_cookie('name')
        return res
ps:学到这里要对登录操作有本质的认识:核心就是cookie的存取

Django操作session

# 设置
request.session['key'] = value  # 可以设置多组
# 获取
request.session.get['key']  # 可以获取多组
"""
服务端保存用户相关状态信息,返回给客户端随机字符串
针对保存,django需要一张表来处理>>>自带的django_session表
ps:django数据库迁移命令会产生一堆默认的表,其中就有一张django_session表
"""

1.设置session内部发生的事情
	1.产生一个随机字符串
	2.表中存储随机字符串与加密数据的对应关系 
	3.并将产生的随机字符串也给客户端发送一份并让其保存
  		sessionid:随机字符串
            
            
2.获取session内部发送的事情
	1.自动获取客户端请求中的随机字符串
	2.自动去存储session数据的表中比对
	3.如果比对成功自动获取并'解密处理'
# django默认的session失效时间是14天

image-20220524155058286

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

其他公用设置项:
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,默认修改之后才保存(默认)

CBV添加装饰器

from django import views
'''需要借助于一个专门的装饰器模块'''
from django.utils.decorators import method_decorator
# 方式一:直接在类中的某个方法上添加
class MyLoginView(views.View):
    @method_decorator(login_auth)
    def get(self, request):
        return HttpResponse('from CBV get view')

    def post(self, request):
        return HttpResponse('from CBV post view')
    
# 方式二:直接在类名上添加并指定
@method_decorator(login_auth, name='get')
class MyLoginView(views.View):
    def get(self, request):
        return HttpResponse('from CBV get view')

    def post(self, request):
        return HttpResponse('from CBV post view')

# 方式三:重写dispatch方法并添加作用于类中所有的方法
class MyLoginView(views.View):
    def get(self, request):
        return HttpResponse('from CBV get view')

    def post(self, request):
        return HttpResponse('from CBV post view')

    @method_decorator(login_auth)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

django中间件

# 回忆django请求生命周期流程图
是django的门户 自带七个中间件 每个都有各自对应的功能

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

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

自定义中间件

"""
1.创建一个任意名称的文件夹
2.在该文件夹内创建一个任意名称的py文件
3.在该py文件内编写中间件类
4.配置文件中注册
"""

必须要掌握的方法

# 1.process_request
请求来的时候会从上往下一次执行配置文件中注册了的中间件里面的process_request方法,如果没有则直接跳过
如果该方法自己返回了HttpResponse对象,那么请求不在继续往后直接返回相应的数据
# 2.process_response
响应走的时候会从下往上依次执行配置文件中注册了的中间件里面的process_response方法,如果没有则直接跳过
如果该方法自己返回了HttpResponse对象,那么响应会替换成改HttpResponse对象数据,而不再是视图函数想要返回给客户端的数据
  """如果process_request返回了HttpResponse对象 那么会从当前位置从下往上执行每一个process_response"""
# 代码:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, render, redirect


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就是视图函数返回给客户端的数据


class MyMdd2(MiddlewareMixin):
    def process_request(self, request):
        print('自定义中间件:from MyMdd2 process_request')
        # return HttpResponse('from MyMdd2 process_request ')
    def process_response(self, request,response):
        print('自定义中间件,from MyMdd2 process_response')
        return HttpResponse('哈哈,中途掉包')
        # return response  # response就是视图函数返回给客户端的数据

执行顺序:

image-20220524182912603

需要了解的方法

1.process_view
	路由匹配成功之后执行视图之前从上往下执行配置文件中注册了的中间件里面的process_view方法
2.process_template_response
	视图函数执行完毕之后返回的对象中含有render属性对应一个render方法
    则会从下往上执行配置文件中注册了的中间件里面的process_template_response方法
3.process_exception
	视图函数执行过程中报错并在返回响应的时候会从下往上执行配置文件中注册了的中间件里面的process_exception
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, render, redirect


class MyMdd1(MiddlewareMixin):
    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 MyMdd1 process_view')

    def process_template_response(self, request, response):
        print('自定义中间件:from MyMdd1 process_template_response')
        return response

    def process_exception(self, request, exception):
        print(exception)
        print('自定义中间件:from MyMdd1 process_exception')


class MyMdd2(MiddlewareMixin):
    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')

    def process_template_response(self, request, response):
        print('自定义中间件:from MyMdd2 process_template_response')
        return response

    def process_exception(self, request, exception):
        print(exception)
        print('自定义中间件:from MyMdd2 process_exception')

代码执行流程

image-20220524214030314

csrf跨站请求伪造

# 前戏
	钓鱼网站:一个模仿正规网站的网址 诱骗用户在该网站上做本应该在正规网站上做的操作,从而获取到该用户在正规网站上的数据甚至是财产
  eg:假设我们需要登录网页完成转账操作
    我们不小心登录到了钓鱼网站 填写了账户 密码 对方账户等信息
    点击转账之后我们账户的钱确实减少了 但是对方账户却变成了一个你从来不认识的人
  原理:将收款人的账号 提前写成犯罪分子的然后隐藏 暴露给用户一个没有name属性的标签写着玩

简单模拟

# view.py
def ab_csrf(request):
    if request.method == "POST":
        current_user = request.POST.get('current_user')
        target_user = request.POST.get('target_user')
        money = request.POST.get('money')
        return HttpResponse(f"{current_user}给{target_user}转了{money}元")
    return render(request, 'ab_csrf.html')
# html
<h2>我是正规网站</h2>
<form action="" method="post">
    <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>

# 钓鱼网站
<h2>我是钓鱼网站</h2>
<form action="http://127.0.0.1:8000/ab_csrf" method="post">
    <p>当前账户:<input type="text" name="current_user"></p>
    <p>目标账户:<input type="text"></p>
    <p style="display: none">目标账户:<input type="text" name="target_user" value="jason"></p>
    <p>当前账户:<input type="text" name="money"></p>
    <input type="submit">
</form>

be1ce528350357e27faf0da305f195e

csrf解决策略

"""针对csrf相关的校验有很多种方式 django只是提供了一些而已"""
# 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>
# ajax请求
1.方式1:页面任意位置先写{% csrf_token %} 之后获取数据     <script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'current_user':$('input[name="current_user"]').val(),
                  'target_user':$('input[name="target_user"]').val(),
                  'money':$('input[name="money"]').val(),
                  'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()
            },
            success:function (args) {
                alert(args)
            }
        })
    })
</script>
2.方式2:模板语法直接获取
    'csrfmiddlewaretoken':'{{ csrf_token }}'

通用解决方案:js脚本自动处理

也只能适用于ajax提交  form表单还是需要额外指定

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);
    }
  }
});

'''
将上面的文件配置到你的Django项目的静态文件中,在html页面上通过导入该文件即可自动帮
我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入
jQuery,因为这个配置文件内的内容是基于jQuery来实现的)
'''
posted @ 2022-05-24 22:54  香菜根  阅读(34)  评论(0编辑  收藏  举报