day59 csrf auth

importlib模块

#bbb.py
name='from bbb'

#aaa.py
import importlib

res = 'lib.bbb'
# 利用字符串的形式导入模块
md = importlib.import_module(res)  # from lib import bbb
print(md)  # 该模块字符串最小单位只能到文件名
# <module 'lib.bbb' from 'D:\\pycharm\\前端\\untitled\\import_idea\\lib\\bbb.py'>
print(md.name)  # from bbb

基于django中间件的思想 实现功能的配置使用

通知功能,邮件,短信,微信发送

#notify.py
def send_email(content):
    print('邮箱通知%s'%content)

def send_msg(content):
    print('短信通知%s'%content)

def send_wechat(content):
    print('微信通知%s'%content)
#start.py
from 初级思想.notify import *

def send_all(content):
    send_msg(content)
    send_email(content)
    send_wechat(content)
if __name__ == '__main__':
        send_all('再坚持一天就周末了')

模仿django

# notify  email.py
class Email(object):
    def __init__(self):
        pass #发送邮件需要的前期准备

    def send(self,content):
        print('邮件通知:%s'%content)
        
#notify  msg.py
class Msg(object):
    def __init__(self):
        pass  # 发送短信需要的前期准备

    def send(self, content):
        print('短信通知:%s' % content)

#settings.py
NOTIFY_LIST=[
    'notify.email.Email',
    'notify.msg.Msg',
    'notify.wechat.WeChat',
    'notify.qq.Qq',
]
        

# notify  __init__.py
import importlib
import settings

def send_all(content):
    for path in settings.NOTIFY_LIST:#'notify.msg.Msg',
        module_path,cls_name=path.rsplit('.',maxsplit=1)#module_path='notify.msg' cls_name='Msg'
        md=importlib.import_module(module_path)#from notify import email
        cls=getattr(md,cls_name)#通过反射 获取到文件中类的名字
        obj=cls()#实例化一个个类的对象
        obj.send(content)
        
 # start.py
from notify import *

send_all('好嗨哟')

跨站请求伪造csrf

钓鱼网站为例:
写一个跟中国正规网站一模一样的页面,用户输入用户名,密码,对方账户,转账金额,提交。请求确实是朝中国银行发送的,钱也扣了,但是对方账户变了,变成了钓鱼网站提前设置好的账户
实现:
在写form表单的时候,让用户填写对方账户input框没有name属性,而是你自己在内部偷偷隐藏了一个具有name属性的input框,并且value值是自己的账户,然后将这个标签隐藏起来
模拟该现象的产生:创建两个django项目

解决该问题:
只处理本网站发送的post请求

form表单 csrf_token

<form action="" method="post">
    {% csrf_token %}
    <p>username: <input type="text" name="username"></p>
    <p>target_account: <input type="text" name="target_user"></p>
    <p>money: <input type="text" name="money"></p>
    <input type="submit">
</form>

在前端显示的是:
<input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">

ajax csrf_token

方式一

较为繁琐

先在页面任意的位置书写{% csrf_token %},然后再发送ajax请求的时候,通过标签查找获取随机字符串添加到data自定义对象即可

{% csrf_token %}
<button id="d1">点击发送ajax</button>
<script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},
            success:function (data) {
                alert(data)
            }
        })
    })
</script>

方式二

较为简单

{% csrf_token %}
<button id="d1">点击发送ajax</button>
<script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
            success:function (data) {
                alert(data)
            }
        })
    })
</script>

方式三

官网提供的文件,是最通用的一种方式,直接新建js文件拷贝代码,导入即可。不需要写任何的csrf相关的代码。

拷贝地址

在static里新建一个js文件,再在settings里配置static
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);
    }
  }
});

在html导入即可

{% csrf_token %}
<button id="d1">点击发送ajax</button>
<script src="/static/setup.js"></script>
<script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username':'jason'},
            success:function (data) {
                alert(data)
            }
        })
    })
</script>

csrf相关的装饰器

csrf_exempt 不校验

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

@csrf_exempt #不校验
def index(request):
    return HttpResponse('index')

csrf_protect 校验

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

@csrf_protect #校验
def login(request):
    return HttpResponse('login')

csrf装饰器在CBV上的特例

csrf_exempt 不校验

csrf_exempt 这个装饰器只能给dispatch装才能生效

from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django import views
from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt,name='dispatch')
class MyIndex(views.View):
    # @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self,request):
        return render(request,'transfer.html')

    def post(self,request):
        return HttpResponse('OK')

csrf_protect 校验

csrf_protect 方式全部都可以,在哪里都会生效,和普通装饰器装饰CBV一致

from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django import views
from django.utils.decorators import method_decorator
@method_decorator(csrf_protect,name='dispatch')
class MyIndex(views.View):
    # @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    # @method_decorator(csrf_protect)
    def get(self,request):
        return render(request,'transfer.html')

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

django settings源码剖析

django有两个配置文件
一个是暴露给用户可以设置的
一个是内部全局的(用户配置了就用用户的,用户没有配置就用自己的)

先加载全局配置,给对象设置。然后再加载局部配置,再给对象设置。一旦有重复的项,后者覆盖前者。

django auth模块

在使用auth模块的时候 ,要用就用全套

1.创建用户

from django.contrib.auth.models import User
User.objects.create(username=username,password=password)  # 不可用  密码不是加密的
User.objects.create_user(username=username,password=password)#创建普通用户,密码自动加密
User.objects.create_superuser(username=username,password=password,email='[email protected]')#创建超级用户 邮箱也要写入

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

from django.contrib import auth
use_obj=auth.authenticate(request,username=username,password=password)#自动给你加密密码 然后去数据库校验,request可以不写
必须传用户名和密码 缺一不可

3.保存用户登录状态

auth.login(request,use_obj)
'''只要执行了这句话,之后在任意位置通过request.user获取当前登录用户对象'''

4.判断当前用户是否登录

request.user.is_authenticated()

5.校验原密码是否正确

request.user.check_password(old_password)#布尔值

6.修改密码

request.user.set_password(new_password)
request.user.save()#必须要写

7.注销

auth.logout(request)

8.检验用户是否登录装饰器

局部配置

from django.contrib.auth.decorators import login_required
# @login_required
@login_required(login_url='/lgg/')

全局配置

#settings配置文件中直接配置
LOGIN_URL='/login/'
@login_required

扩展auth_user表字段

方式一

利用一对一外键字段关系

class UserDetail(models.Model):
    phone = models.BigIntegerField()
    user = models.OneToOneField(to='User')

方式二

利用继承关系

一定要注意 要去配置文件配置
AUTH_USER_MODEL='app01.Userinfo' #应用名.表名
这么写完之后,之前所有的auth模块功能全都以建的表为准

from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
    phone=models.BigIntegerField()
    register_time=models.DateField(auto_now_add=True)

基于配置文件的编程思想

基于django settings源码实现自己项目配置文件插拔式设计

#lib  conf __init__
import importlib
from lib.conf import global_settings
import os

class Settings(object):
    def __init__(self):
        for name in dir(global_settings):
            if name.isupper():
                setattr(self,name,getattr(global_settings,name))
            #获取暴露给用户的配置文件字符串路径
            module_path=os.environ.get('xxx')
            md=importlib.import_module(module_path)
            for name in dir(md):
                if name.isupper():
                    k=name
                    v=getattr(md,name)
                    setattr(self,k,v)
setting=Settings()

#lib  conf  global_settings
NAME = '我是暴露给用户的自定义配置'

#conf settings
NAME ='我是暴露给用户的自定义配置'

#start
import os
import sys
BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)

if __name__ == '__main__':
    os.environ['xxx']='conf.settings'
    from lib.conf import settings
    print(settings.NAME)

猜你喜欢

转载自www.cnblogs.com/zqfzqf/p/11992781.html