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='123@qq.com')#创建超级用户 邮箱也要写入
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)
                    
                
                
            
        
浙公网安备 33010602011771号