django学习笔记

今日内容概要

  • csrf跨站请求伪造
  • csrf相关装饰器
  • auth认证模块
  • 基于django中间件设计项目功能

今日内容详细

csrf跨站请求伪造

简介

钓鱼网站:一个模仿正规网站的网址 诱骗用户在该网站上做本应该在正规网站上做的操作,从而获取到该用户在正规网站上的数据甚至是财产。eg:假设我们需要登录网页完成转账操作,我们不小心登录到了钓鱼网站,是一个跟银行一摸一样的网址页面,用户再该页面上转账账户的钱会减少,但是受益人却不是自己想要转账的那个人。

模拟钓鱼网站:

一台计算机上两个服务端不同端口启动,钓鱼网站提交地址改为正规网站地址。

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

<p>当前账户:<input type="text" name="username"></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>

如何预防钓鱼网站:

csrf策略:通过在返回的页面上添加独一无二的标识信息从而区分正规网站和钓鱼网站的请求。

csrf操作

form表单:

<form action="" method="post">
{% csrf_token %}
<p>当前账户:<input type="text" name="username"></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模板语法,然后利用标签查找和值获取,手动添加

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

方式2:直接利用模板语法即可

'csrfmiddlewaretoken':'{{ csrf_token }}'

方式3:通用方式(js脚本)扩展性最高

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

csrf相关装饰器

当整个网站默认都不校验csrf,但是局部视图函数需要校验,如何处理

csrf_protect 校验csrf

当整个网站默认都校验csrf,但是局部视图函数不需要校验,如何处理

csrf_exempt 不校验csrf

针对FBV

from django.views.decorators.csrf import csrf_protect,csrf_exempt

# @csrf_protect
@csrf_exempt
def home(request):
    return HttpResponse('哈哈哈')

针对CBV

针对CBV不能直接在方法上添加装饰器 需要借助于专门添加装饰器的方法

csrf_protect:三种CBV添加装饰器的方式都可以
csrf_exempt:只有方式3可以生效(给重写的dispatch方法装)
# @method_decorator(csrf_protect,name='post')  # 可以    # 方式2:指名道姓的添加
# @method_decorator(csrf_exempt,name='post')  # 无效
class MyView(views.View):
    # @method_decorator(csrf_protect)  # 可以   # 方式3:影响类中所有的方法
    @method_decorator(csrf_exempt)  # 有效
    def dispatch(self, request, *args, **kwargs):
        return super(MyView, self).dispatch(request,*args,**kwargs)

    # @method_decorator(csrf_protect)  # 可以
    # @method_decorator(csrf_exempt)  # 无效
    def post(self,request):   # 方式1:指名道姓的添加
        return HttpResponse('Home Post view')

auth认证模块

简介

django执行数据库迁移命令后会产生一个auth_user表,该表可以配合auth模块做用户相关的功能,eg:注册、登录、修改密码、注销...。该表还是django admin后台管理默认的表

django自带的admin后台管理用户登录参考的就是auth_user表。

创建admin后台管理员用户
python manage.py createsuperuser
自动对用户密码进行加密处理并保存

auth模块常见功能

1.创建用户

from django.contrib.auth.models import User
User.object.create_user(username,password)   # 普通用户
User.object.create_superuser(username,password,email)   # 管理员

2.校验用户名和密码是否正确

from django.contrib import auth
auth.authenticate(request,username,password)   # 校验正确返回的是用户对象 错误返回的是None

3.用户登录

auth.login(request,user_obj)   # 自动帮你操作cookie与session相关

4.判断用户是否登录

request.user.is_authecticated()   # 判断用户是否登录  返回布尔值

5.获取登录用户对象

request.user   # 获取当前登录的用户对象或者是匿名用户

6.校验用户登录装饰器

from django.contrib.auth.decorators import login_required
跳转局部配置
login_required(login_url='/login/')   # 每次都需要自己写 量大的情况下不方便
跳转全局配置
LOGIN_URL = '/login/'  # 需要在配置文件中添加配置

7.校验密码是否正确

request.user.check_password(old_password)   # 自动加密再比对

8.修改密码

request.user.set_password(new_passowrd)   # 临时修改密码
request.user.save()   # 将修改操作同步到数据库中

9.注销登录

auth.logout(request)   # 自动清除cookie和session

auth_user表切换

我们想使用auth模块的方法并且还想扩展auth_user表字段

方式1:编写一对一表关系(了解)

方式2:类继承(推荐)

# models.py
from django.contrib.auth.models import AbstractUser

class Userinfo(AbstractUser):
    '''扩展auth_user表中没有的字段  不能冲突'''
    phone = models.BigIntegerField()
    desc = models.TextField()

# settings.py
'''告诉auth模块 不再使用auth_user 而是使用自定义的表'''
AUTH_USER_MODEL = 'app01.Userinfo'

注意:

  1. 类继承之后,需要重新执行数据库迁移命令,并且库里面是第一次操作才可以
  2. auth模块所有的方法都可以直接在自定义模型类上面使用,自动切换参照表

基于django中间件设计项目功能

importlib模块:可以通过字符串的形式导入模块

常规导入方式

方式1import  句式

方式2from ... import ... 句式
from bbb import b
from bbb.b import name  # 可以直接导变量数据
print(b)  # <module 'bbb.b' from '/Users/jiboyuan/PycharmProjects/day64_1/bbb/b.py'>
print(b.name)

字符串导入方式

import importlib
module_path = 'bbb.b'
res = importlib.import_module(module_path)
print(res.name)
module_path1 = 'bbb.b.name'
importlib.import_module(module_path1)  # 不可以 最小导入单位是模块文件级别

以发送提示信息为需求编写功能的案例

方式1:简单的函数式封装

方式2:配置文件插拔式设计:

# settings
NOTIFY_FUNC_LIST = [
    'notify.qq.QQ',
    'notify.email.Email',
    'notify.msg.Msg',
    'notify.weixin.WeiXin',
]
# __init__
import settings
import importlib
def send_all(msg):
    # 1.循环获取配置文件中字符串信息
    for str_path in settings.NOTIFY_FUNC_LIST:  # 'notify.qq.QQ'
        # 2.切割路径信息
        module_path, class_str_name = str_path.rsplit('.', maxsplit=1)  # ['notify.qq','QQ']
        # 3.根据module_path导入模块文件
        module = importlib.import_module(module_path)  # from day64.notify import qq
        # 4.利用反射获取模块文件中对应的类名
        class_name = getattr(module, class_str_name)  # Email  Msg  QQ
        # 5.实例化
        obj = class_name()
        # 6.调用发送消息的功能
        obj.send(content)

链式调用:

写一个类,类中的方法,每次都返回对象本身
class Person:
    def change_name(self,name):
        self.name=name
        return self
    def change_age(self,age):
        self.age=age
        return self

person.change_name(lqz)
person.change_age(19)

person.change_name(lqz).change_age(19)
posted @   空白o  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示