• csrf及auth模块


    目录

    CSRF简介

    用途

    模拟

    预防

    csrf校验策略

    1.Token的构成

    2.form表单操作csrf

     3.Ajax操作csrf 

    CSRF添加装饰器的方法

    auth模块常见方法

     auth常见功能

    创建用户

    校验用户名或密码是否非正确

    用户登录,保存用户状态

    判断用户是否登录

    获取登录用户对象

    校验用户登录装饰器

    校验密码是否正确

    修改密码

    注销登录

    auth_user表切换方法

    基于中间件思想的功能插拔式设计

    1.模块的导入方法

    2.类中间件导入方式    

        2.2配置文件插拔设计

     auth扩展表字段

    扩展方式一 : 建立一对一外键关系

    扩展方式二 : 继承 AbstractUser 类来扩写 (步骤)

    如果 auth_user 表已经存在


    CSRF简介

    CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding, 缩写为:CSRF/XSRF

    用途

    CSRF可以用来做钓鱼网站:  假设是一个和银行一模一样的网址页面,用户在该页面上转账账户的钱就会减少,三十受益人却不是自己指定想要转账的那个人.

    你可以这么理解CSRF共计:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你的名义发送邮件,发信息,盗取你的账号,甚至于购买商品,虚拟货币转账...造成的问题包括:个人隐私泄露以及财产安全

    模拟

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

    • 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

    • 2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

    • 3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

    • 4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;

    • 5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

    预防

    • csrf策略:通过在返回的页面上添加独一无二的标识信息从而区分正规网站和钓鱼网站的请求
    • CSRF防护的一个重点就是要对用户凭证进行处理,通过这种机制可以对用户的请求合法是否合法进行判断,判断是不是跨站攻击的行为。因为用户凭证是Cookie中存储的,所以防护机制的处理对象也是Cookie的数据,我们要在防护的数据中加入签名校验,并对数据进行生命周期时间的管理,就是数据过期管理。

    csrf校验策略

    1.Token的构成


        消息[msg]:而msg本身也有两部分组成:一部分:随即字符串,过期时间戳。
        分隔符[separator]:用于分割msg部分与加密后生成的signature签名部分,这里用的是"."
        签名[signature]:singnature.signature签名,是对“msg消息”用特定算法进行加密后的字符串
        token = base64(msg)格式化..base64(sha256("密码",msg))
        Token由被base64的msg编码穿+256加密msg再进行Base64编码,两个字符串的内容结合
     


    2.form表单操作csrf

    1.    <h1>这是一个真实的网站h1>
    2.     <form action="" method="post">
    3.         {% csrf_token %}
    4.     form>

     
    3.Ajax操作csrf 


        方法一:先编写csrf模板语法,然后利用标签查找和值获取,手动添加
          

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


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

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


        方法三:通用方法(js脚本)CV大法即可


        更多详情请见: https://docs.djangoproject.com/en/1.11/ref/csrf/

    1. function getCookie(name) {
    2. var cookieValue = null;
    3. if (document.cookie && document.cookie !== '') {
    4. var cookies = document.cookie.split(';');
    5. for (var i = 0; i < cookies.length; i++) {
    6. var cookie = jQuery.trim(cookies[i]);
    7. // Does this cookie string begin with the name we want?
    8. if (cookie.substring(0, name.length + 1) === (name + '=')) {
    9. cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
    10. break;
    11. }
    12. }
    13. }
    14. return cookieValue;
    15. }
    16. var csrftoken = getCookie('csrftoken');
    17. function csrfSafeMethod(method) {
    18. // these HTTP methods do not require CSRF protection
    19. return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    20. }
    21. $.ajaxSetup({
    22. beforeSend: function (xhr, settings) {
    23. if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
    24. xhr.setRequestHeader("X-CSRFToken", csrftoken);
    25. }
    26. }
    27. });

    CSRF添加装饰器的方法

    1.当整个网站默认都不校验csrf,但是有局部视图函数需要校验
        关键字:@csrf_protect
    2.当整个网站默认都校验csrf,但是有局部视图函数不需要校验
        关键字:@csrf_exempt
    3.两种装饰器的使用
        先导入装饰器:
            form django.views.decorators.csrf import csrf_protect,csrf_exempt

    4.针对FBV添加装饰器

    1. @csrf_protect
    2. def home(request):
    3. return HttpResponse('哈哈哈')
    4. @csrf_exempt
    5. def index(request):
    6. return HttpResponse('嘿嘿嘿')


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

    1. from django import views
    2. from django.utils.decorators import method_decorator

    6.针对CBV添加装饰器

    1. @method_decorator(csrf_protect, name='post') # 方法二:指名道姓的添加
    2. class MyHome(views.View):
    3. @method_decorator(csrf_protect) # 影响类中所有的方法
    4. def dispatch(self, request, *args, **kwargs):
    5. super(MyHome, self).dispatch(request, *args, **kwargs)
    6. def get(self, request):
    7. return HttpResponse('Home Get view')
    8. @method_decorator(csrf_protect) # 方法一:直接在该函数头上添加
    9. def post(self, request):
    10. return HttpResponse('Home Post view')

     7.针对csrf_exempt这个装饰器只有方法三有效,其他的装饰器上述方法都可以直接使用(包括自定义装饰器)

    auth模块常见方法

    1.我们在开发一个网页的时候无可避免的需要设计实现网站的用户系统,此时我们需要实现包括用户注册、用户登录、注销、修改密码等功能。为了节省这个麻烦的过程,Django自带了强大的用户认证系统Auth,它默认使用auth_user表来存储用户的数据。
    2.该表还是Django admin后台管理默认的表
        django admin后台管理员账号创建
    3.创建方法:
        python manage.py createsuperuser
    4.导入auth模块
        from django.contrib import auth

    字段释义
    idID
    password密码
    last_login最后登录时间
    is_superuser是否是管理员
    username用户名
    first_name
    last_name
    email邮箱
    is_staff是否是工作人员
    is_active是否激活
    date_joined创建时间

     auth常见功能

    创建用户

    1. from django.contrib.auth.models import User
    2. 1.普通用户
    3. user = User.objects.create_user(username='用户名',password='密码',...)
    4. 2.管理员用户,必须要有email
    5. user = User.object.create_superuser(username='用户名',password='密码',email='邮箱',...)

    校验用户名或密码是否非正确

    1.作用:提供了用户认证功能,即验证用户名以及密码是否正确
    2.必须传入两个参数:username & password
    3.校验成功返回True,失败返回None

    1. from django.contrib import auth
    2. user_obj = auth.authenticate(request,username=username,password=password)
    3. if user_obj:
    4. print(user_obj.username)
    5. print(user_obj.password)
    6. else:
    7. print('验证失败')

    用户登录,保存用户状态

    1.作用:该函数接受了一个HttpResponse对象,以及一个经过认证的User对象
    2.实现一个用户登录功能,本质上会在后端为用户生成session数据存在于session表中
    3.只要执行了该方法,你就可以在任何地方通过request.user获取到当前登录的用户对象,否则拿到的就是一个匿名用户对象也就是none
        auth.login(request,user_obj)  # 内部调用的就是request.session['key']=user_obj

    判断用户是否登录

    1.作用:用来判断当前请求是否用过了认证
    视图中使用

    1.  if not request.user.is_authenticated():
    2.     print('未登入,请先登入')

    模板中使用

    1.     {% if request.user.is_authenticated %}
    2.         {{ request.user.username }} 欢迎回家
    3.     {% else %}
    4.     {% endif %}

    获取登录用户对象

    1.作用:获取当前登录的用户对象
        user_obj = request.user

    校验用户登录装饰器

    1.作用:一个装饰器工具,用来快捷的给某个视图添加登录校验
        from django.contrib.auth.decorators import login_required
    使用方式一: 直接在视图函数上添加
     

    1.    @login_required(login_url='/login/')  # 需要指定url
    2.     @login_required  # 全局配置
    3.     def logout_func(request):
    4.         auth.login(request)
    5.         return redirect("/login/")
    6.  


    方法二:在配置文件中全局配置
     

        LOGIN_URL = '/login/'

    校验密码是否正确

    1.作用:提供一个检查密码是否正确的方法,需要提供当前请求用户的密码
    2.密码正确返回True,否则返回False
        if user.check_password('你的密码old_password')
            print('ok')

    修改密码

    1.作用:提供一个需要改密码的方法,接受要设置新密码作为参数
    2.设置完一定要调用用户对象的save方法
        request.user.set_password(new_password)
        request.user.save()

    注销登录

    1.作用:该函数接收一个HttpResponse对象,无返回值
    2.当调用该函数时,当前请求的session信息会全部清除,该用户既没有登录,使用该函数也不会报错
    auth.login(request)  # 内部使用的就是request.session.flush()

    auth_user表切换方法

    1.models.py

    1. from django.contrib.auth.models import AbstractUser
    2.  
    3. class Userinfo(AbstractUser):
    4.     '''扩展auth_user表中没有的字段'''
    5.     phone = models.BigIntegerField()
    6.     desc = models.TextField()


    2.setting.py
      

     AUTH_USER_MODEL = 'app01.Userinfo'

    基于中间件思想的功能插拔式设计

    1.模块的导入方法


        1.1import 句式

        1.2from ... import ...
        1.3类似中间件功能的导入方式(importlib)

    1.  s1 = 'dajngo.bbb.b'
    2.     print(s1.rsplit('.',maxsplit=1))  # 底层原理
    3.     import importlib
    4.     res = importlib.import_module(s1)  # 自动将点号做标记来切割  from bbb import b
    5.     print(res.name)

    2.类中间件导入方式
        

    2.1简单的函数式封装
     

    1.    def send_qq(content):
    2.         print('qq消息通知:',content)
    3.  
    4.     def send_wx(content):
    5.         print('微信消息通知:',content)
    6.  
    7.     def send_mag(content):
    8.         print('短信消息通知:',content)
    9.  
    10.  
    11.     def seed_all(content):
    12.         send_qq(content)
    13.         send_wx(content)
    14.         send_mag(content)
    15.  
    16.  
    17.     if __name__ == '__main__':
    18.         seed_all('累了,毁灭吧')


        2.2配置文件插拔设计


     auth扩展表字段

    auth_user 中的字段有限, 想要在 auth_user 表中添加新的字段, 我们可以对其进行扩展。

    扩展方式一 : 建立一对一外键关系

    新建一个模型类, 比如要添加 Phone 字段, 在该模型内中写入, 并添加 User 的外键字段

    1. from django.contrib.auth.models import User 
    2. class user_detail(models.Model):
    3.     user=models.OneToOneField(to='User')
    4.     phone=models.CharField(max_length=32)

    扩展方式二 : 继承 AbstractUser 类来扩写 (步骤)

    1. 首先大前提是没有生成 auth_user 表(也就是没进行数据库迁移操作)(有的话需要删干净迁移记录和表)
     
        2. 书写一个类, 并继承 AbstractUser 类
     
        3. 在类中可以书写你需要扩展的字段, 也可以重写原来的字段
       

    1.     class MyAuthUser(AbstractUser):
    2.             username=models.CharField(max_length=12)  # 重写字段
    3.             phone=models.CharField(max_length=32)     # 书写新字段
    4.  


        4. 到 setting.py 配置文件中设置 AUTH_USER_MODEL 参数, 不然报错
       

    1.     AUTH_USER_MODEL = "[app名].[类名]"
    2.         AUTH_USER_MODEL = "app01.MyAuthUser"  # 示例
    3.  


        5. 最后进行数据库迁移命令
           

    1. python3 manage.py makemigrations
    2.         python3 manage.py migrate

    如果 auth_user 表已经存在

         1. 先删库 
     
        2. 并清空项目中所有的 makemigrations 而来的迁移记录
     
        3. 再清空源码中admin,auth俩app的 makemigrations 产生的记录

  • 相关阅读:
    2022中国DevOps社区峰会 走进国产数据库的技术创新实践
    .Net8 AddKeyedScoped键值key注册服务异常
    什么情况?周鸿祎和三六零违约,“零元”甩卖哪吒汽车10亿元股权
    「直播回放」使用 PLC + OPC + TDengine,快速搭建烟草生产监测系统
    Ubuntu 17.10的超震撼声音权限
    Linux系统编程——进程中vfork函数
    【组成原理-数据】定点数的编码与运算
    04、JavaWeb启程——数据库
    java面试题
    用Python操作Word文档,看这一篇就对了!
  • 原文地址:https://blog.csdn.net/weixin_67531112/article/details/126842400