zoukankan      html  css  js  c++  java
  • 跨站请求伪造 auth模块

    importlib  利用字符串形式导入模块

    import importlib
    res = 'lib.bbb'
    # 利用字符串的形式导入模块
    md = importlib.import_module(res)  # from lib import bbb
    print(md)  # 该模块字符串最小单位只能到文件名

     

     跨站请求伪造 csrf

    钓鱼网站
      你自己写一个跟中国银行正规网站一模一样的页面
      用户输入用户名 密码 对方账户 转账金额提交
      请求确实是朝中国银行的接口发送的 钱也扣了
      但是对方账户变了 变成了钓鱼网站自己提前设置好的账户

    如何实现
      你在写form表单的时候 让用户填写的对方账户input并没有name属性
      而是你自己在内部偷偷隐藏了一个具有name属性的input框
      并且value值是你自己的账户 然后将该标签隐藏了

    跨站请求伪造解决思路

    解决
      网站在返回给用户一个form表单的时候 会自动在该表单隐藏一个input框
      这个框的value是一个随机字符串 但是网站能够记住每一个浏览器发送的随机字符串

    你以后在写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框 <input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">

    ajax如何解决POST请求csrf校验

    方式1 较为繁琐
    先在页面任意的位置上书写{% csrf_token %}
    然后在发送ajax请求的时候 通过标签查找获取随机字符串添加到data自定义对象即可
    data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},

    方式2 较为简单
    data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},


    方式3 官网提供的文件 最通用的一种方式
    直接新建js文件,放在static下面(注意配置static)拷贝代码 导入即可
    你不需要做任何的csrf相关的代码书写

    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的校验装饰器

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    @csrf_exempt # 不校验 csrf
    def index(request):
    return HttpResponse('index')


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

    csrf的校验装饰器在CBV上有何异同

    # @method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
    @method_decorator(csrf_exempt,name='dispatch') # csrf_exempt
    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')
      # @method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
      def post(self,request):
        return HttpResponse('OK')


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


    """
    csrf_protect方式全都可以 跟你普通的装饰器装饰CBV一致
    """

     django settings源码剖析

    django有两个配置文件
      一个是暴露给用户可以配置的

      一个是内部全局的(用户配置了就用用户的 用户没有配就用自己的)
    obj
    obj.name = 'egon' # 全局
    obj.name = 'jason' # 局部

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

     auth模块简介

    如何创建超级用户(root)
    python3 manage.py createsuperuser


    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
        user_obj = auth.authenticate(request,username=username,password=password)
        # 必须传用户名和密码两个参数缺一不能
      3.保存用户登录状态
        auth.login(request,user_obj)
        # 只要这句话执行了 后面在任意位置 只要你能拿到request你就可以通过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_url='/login/')
        def index(request):
          pass
      全局配置
        settings配置文件中 直接配置
        LOGIN_URL = '/login/'
        @login_required
        def index(request):
          pass
      # 如果全局配置了 局部也配置 以局部的为准

    from django.contrib.auth.models import User
    from django.contrib import auth
    from django.contrib.auth.decorators import login_required
    
    def register(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            # models.User.objects.create(username=username,password=password)
            # 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')  # 创建超级用户   需要邮箱数据
            return HttpResponse('OK')
        return render(request,'register.html')
    
    
    def lgg(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            # 校验当前用户名和密码是否正确
            # models.User.objects.filter(username=username,password=password)
            # res = User.objects.filter(username=username,password=password)  # 密码无法校验
            # print(res)
            res = auth.authenticate(request,username=username,password=password)  # 自动给你加密密码 然后去数据库校验
            # print(res)  # 数据对象
            # print(res.username)
            # print(res.password)  # 密码是密文
            if res:
                # 保存用户登录状态
                # request.session['user'] = 'jason'
                auth.login(request,res)
                """
                只要执行了这一句话 之后你可以在任意位置
                通过request.user获取到当前登录用户对象
                """
                return HttpResponse('ok')
        return render(request,'lgg.html')
    
    
    def get_user(request):
        print(request.user)  # 如果用户没有登录就返回AnonymousUser匿名用户
        print(type(request.user))
        print(request.user.is_authenticated())  # 判断当前用户是否登录
        return HttpResponse('ok')
    
    # @login_required(login_url='/lgg/')  # 局部配置  如果没有登录就跳转到/lgg/登录
    # 或者全局配置,现在配置文件中写 LOGIN_URL = '/lgg/'
    @login_required
    def check_password(request):
        if request.method == "POST":
            old_password = request.POST.get('old_password')
            new_password = request.POST.get('new_password')
            # 校验老密码是否正确
            is_right = request.user.check_password(old_password)
            if is_right:
                request.user.set_password(new_password)
                request.user.save()  # 修改密码一对要保存
        user_obj = request.user
        return render(request,'change_password.html',locals())
    
    
    @login_required
    def logout(request):
        # request.session.flush()
        auth.logout(request)
        return HttpResponse('注销了')

     auth拓展表

    方式1
    利用一对一外键字段关系
    class UserDetail(models.Model):
      phone = models.BigIntegerField()
      user = models.OneToOneField(to='User')

    方式2
    利用继承关系
    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模块功能全都以你写的表为准

    基于djangosettings配置文件实现插拔式设计

    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)  # md = settings
            for name in dir(md):
                if name.isupper():
                    k = name
                    v = getattr(md,name)
                    setattr(self,k,v)
    
    
    settings = Settings()
    import os
    import sys
    
    
    BASE_DIR = os.path.dirname(__file__)
    sys.path.append(BASE_DIR)
    
    
    if __name__ == '__main__':
        # os.environ.setdefault('xxx','conf.settings')
        os.environ['xxx'] = 'conf.settings'
        from lib.conf import settings
        print(settings.NAME)

  • 相关阅读:
    JavaScript数组去重(12种方法,史上最全转载)
    数组从大到小排序的两种方式
    jquery.inArray()和splice()使用小记
    HbuilderX 线上打包Android9.0版本无法更新
    常见的移动端H5页面开发遇到的坑和解决办法
    监听点击物理返回键及mui.fire父子页面传参
    深入理解DOM事件类型系列第三篇——变动事件
    jquery监听div等元素的内容变化
    寒假进度3
    寒假进度2
  • 原文地址:https://www.cnblogs.com/fjn839199790/p/11990812.html
Copyright © 2011-2022 走看看