zoukankan      html  css  js  c++  java
  • django----csrf跨站请求伪造 auth组件 settings源码 importlib模块

    importlib模块

    使用 将需要导入的文件路径 放入 import_module() 里面 即可拿到该路径对应的文件 但是 只能识别到文件 不能识别到文件里的内容

    path = 'bbs.apps'
    import importlib
    res = importlib.import_module(path)
    print(res)
    # <module 'bbs.apps' from 'C:\Users\ld_dragon\Desktop\项目\BBS_project_12\bbs\apps.py'>
    

    csrf跨站请求伪造

    引入:钓鱼网站: 通过制作一个跟正儿八经的网站一模一样的界面 骗取用户输入信息 修改数据去正儿八经的网站提交

     内部原理: 在让用户输入给对方转账的那个input框上做手脚 不给 这个input 设置name 和属性 在内部隐藏一个写好的name value属性input框 这个value就是 钓鱼网站受益人的账号 form 表单数据提交 改为正儿八经的

     防止钓鱼网站的思路
       网站会给返回给用户的form表单页面 偷偷塞一个随机字符串
       请求到来的时候 会先比对随机字符串是否一致 如果不一致 直接拒绝(403)

    该随机字符串有以下特点
       1.同一个浏览器每一次访问都不一样
       2.不同浏览器绝对不会重复

    form表单发送

    form表单发送post请求的时候 需要你仅仅做的就是写一句话{{% csrf_token %}} 这样我们就可以吧 中间件的有个注释打开了 他这个就是来校验你有没有 一个 csrfmiddlewaretoken的东西 没有直接给你403

    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <input type="submit">
    </form>
    <input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">
    

    ajax发送

    1.先在页面上写{% csrf_token %}, 利用标签`` 属name性查找器 查找 获取到该input键值信息

    data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()}
    

    2.直接书写'{{ csrf_token }}' 一定要带引号

    data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}
    

    3.将获取随机键值对的方法写到一个js文件中 之后只需要导入文件即可 在static文件中创建 js文件 和 py文件 把下面代码写入 之后导入就行

    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装饰器

    # cbv装饰器
    from django.utils.decorators import method_decorator
    # 模块的导入   csrf_exempt 不校验  csrf_protect 只校验
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    

    1.当你网站全局都需要校验csrf的时候 有几个不需要校验该如何处理?

    如果是csrf_exempt 只有两种(只能给dispatch装)   特例
                @method_decorator(csrf_exempt,name='dispatch')  # 第二种可以不校验的方式
                class MyView(View):
                    # @method_decorator(csrf_exempt)  # 第一种可以不校验的方式
                    def dispatch(self, request, *args, **kwargs):
                        res = super().dispatch(request, *args, **kwargs)
                        return res
    
                    def get(self,request):
                        return HttpResponse('get')
    
                    def post(self,request):
                        return HttpResponse('post')
    
    装饰器中只有csrf_exempt是特例,其他的装饰器在给CBV装饰的时候 都可以有三种方式
    

    2.当你网站全局不校验csrf的时候 有几个需要校验又该如何处理?

    如果是csrf_protect 那么有三种方式
    # 第一种方式
    # @method_decorator(csrf_protect,name='post')  # 有效的
    class MyView(View):
        # 第三种方式
        # @method_decorator(csrf_protect)
        def dispatch(self, request, *args, **kwargs):
            res = super().dispatch(request, *args, **kwargs)
            return res
    
        def get(self,request):
            return HttpResponse('get')
        # 第二种方式
        # @method_decorator(csrf_protect)  # 有效的
        def post(self,request):
            return HttpResponse('post')
    

    auth模块

    ​ 建议:在使用auth模块的时候 要用就用它的全套

    如何创建超级用户(root)

    python3 manage.py createsuperuser
    

    创建用户

    from django.contrib.auth.models import User
    User.objects.create_user(username=username,password=password)  # 创建普通用户    密码自动加密
    User.objects.create_superuser(username=username,password=password
    

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

    from django.contrib import auth
    user_obj = auth.authenticate(request,username=username,password=password)
    # 必须传用户名和密码两个参数缺一不能
    

    保存用户登录状态

    auth.login(request,user_obj)
    # 只要这句话执行了 后面在任意位置 只要你能拿到request你就可以通过request.user获取到当前登录的用户对象
    

    判断当前用户是否登录

    request.user.is_authenticated()
    

    校验原密码是否正确

    request.user.check_password(old_password)
    

    修改密码

    request.user.set_password(new_password)
    request.user.save()  # 千万不要忘了
    

    注销

    auth.logout(request)
    

    校验用户是否登录 装饰器

    from django.contrib.auth.decorators import login_required
    局部配置
    @login_required(login_url='/login/')
    def index(request):
        pass
    全局配置
    settings配置文件中 直接配置
    LOGIN_URL = '/login/'
    @login_required
    def index(request):
        pass
    # 如果全局配置了 局部也配置  以局部的为准
    

    如何扩展auth_user表字段

    利用一对一外键字段关系
    class UserDetail(models.Model):
        phone = models.BigIntegerField()
        user = models.OneToOneField(to='User')
    
    利用继承关系  
    from django.contrib.auth.models import AbstractUser
    class Userinfo(AbstractUser):
        phone = models.BigIntegerField()
        register_time = models.DateField(auto_now_add=True)
    
        # 一定要注意 还需要去配置文件中配置
        AUTH_USER_MODEL = 'app01.Userinfo'  # 应用名.表名
        # 这么写完之后 之前所有的auth模块功能全都以你写的表为准 
    

    settings源码分析

    django中使用配置文件:

    # 建议从conf中导入配置文件 而非直接导入该项目的配置文件
    from django.conf import settings
    # 还有个全局的
    from django.conf import settings,global_settings
    
    一个是暴露给用户可以配置的
    一个是内部全局的(用户配置了就用用户的 用户没有配就用自己的)
    # 先加载全局配置 给对象设置 然后在加载局部配置  再给对象设置 一旦有重复的项  后者覆盖前者
    
    if __name__ == "__main__":
        # settings文件配置到环境变量
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "auth_learn.settings")
        
    settings = LazySettings()
    
    # global_settings就是一个django内部的全局配置文件
    from django.conf import global_settings
    class Settings(object):
        def __init__(self, settings_module):
            # 这句话就是遍历全局配置, 将所有的属性添加到settings对象中
            for setting in dir(global_settings):
                # 这里也说明了为什么属性需要大写
                if setting.isupper():
                    setattr(self, setting, getattr(global_settings, setting))
    
            # store the settings module in case someone later cares
            self.SETTINGS_MODULE = settings_module
           # 这里就是动态的将我们用户的自定义配置文件模块导入 
            mod = importlib.import_module(self.SETTINGS_MODULE)
            self._explicit_settings = set()
            # 遍历用户自定义配置文件
            for setting in dir(mod):
                # 如果我们配置的属性不是大写, 就会无效
                if setting.isupper():
                    # 获取用户的配置属性
                    setting_value = getattr(mod, setting)
                    # 将我们配置的属性添加到settings配置文件中, 或者覆盖掉
                    # Django默认的配置属性.
                    setattr(self, setting, setting_value)
                    self._explicit_settings.add(setting) 
    
  • 相关阅读:
    docker swarm使用keepalived+haproxy搭建基于percona-xtradb-cluster方案的高可用mysql集群
    docker搭建基于percona-xtradb-cluster方案的mysql集群
    flask实现基于elasticsearch的关键词搜索建议
    tcp === udp
    re 模块===正则表达式
    模块===包
    析构方法====
    python===属性--类方法
    python====接口类 抽象类===19
    python==继承===18
  • 原文地址:https://www.cnblogs.com/lddragon1/p/11992630.html
Copyright © 2011-2022 走看看