• Django之csrf跨站请求伪造,auth认证模块


    一.csrf跨站请求伪造:

          用钓鱼网站模仿正规网站从而达到瞒天过海的操作,具体的操作如下:

            首先,开一个正规网站服务器(为了模仿钓鱼,把csrf中间件关了):

            视图:

    def index(request):
        username = request.POST.get('username')
        money = request.POST.get('money')
        others = request.POST.get('others')
    
        return HttpResponse('%s 给 %s 成功转了 %s元!!! '%(username,others,money))

           前端:

    <h1>正规网址</h1>
    <form action="" method="post">
    {#    {% csrf_token %}#}
        <p>username:<input type="text" name="username"></p>
        <p>money:<input type="text" name="money"></p>
        <p>对方账户:<input type="text" name="others"></p>
        <input type="submit">
    </form>

          现在由于不小心进了一个与这个一模一样页面的网站,假设正规页面端口号8000,钓鱼8001:

         视图:

    def index(request):
        return render(request,'index.html')

        前端(偷梁换柱):

    <h1>钓鱼网站</h1>
    <form action="http://127.0.0.1:8000/index/" method="post">
        <p>username:<input type="text" name="username"></p>
        <p>money:<input type="text" name="money"></p>
        <p>对方账户:<input type="text"></p>
        <input type="text" name="others" value="huangyan" style="display: none">
        <input type="submit">
    </form>

        操作如下:

     点完提交:

        这时候出于正义,我们要杜绝此类恶行发生,掏出了csrf中间件:

     'django.middleware.csrf.CsrfViewMiddleware',

       此时,再提交试试:

      看到这我们就放心了,那么回头想想这里面发生了什么?

    <input type="hidden" name="csrfmiddlewaretoken" value="oEiTkGw3gB5zKUegA3OPvoBgbKVTp0BoAzbvluq0dFhd7NTUll0MrUJEZtCabShs">

     此处有一个隐藏的键值对,包含了一个动态value值,每次提交都会更新,在比对时杜绝钓鱼网站的请求

     那么自己要用,该怎么产生这个键值对来通过csrf中间件呢?

    <h1>正经网址</h1>
    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <p>money:<input type="text" name="money"></p>
        <p>对方账户:<input type="text" name="others"></p>
        <input type="submit">
    </form>

    加上  {% csrf_token %} 就可以了,除了form表单,如果要传一些json字符串就要用到ajax,又该怎么办?

    <button>ajax请求</button>
    
    <script>
        $('button').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data:{'name':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>

    假如有部分的视图函数不想走csrf中间件的校验,可以加一个装饰器:

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    
    @csrf_exempt
    def home(request):
        return HttpResponse('home')

    反过来,假如csrf中间件禁用了,现在想用它的校验:

    @csrf_protect
    def login(request):
        return HttpResponse('login')

    现在再来试试CBV:

    路由:

      url(r'^reg/',views.Reg.as_view()),

    视图:

    from django.views import View
    
    
    from django.utils.decorators import method_decorator
    # 装饰csrf装饰器的时候,只有这两种固定写法
    @method_decorator(csrf_exempt,name='dispatch')  # 第一种
    class Reg(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')

    二.auth认证模块

     在数据库中创建一个表,往里面新建一条记录:

    然后看到的表记录是这样的:

    开始来登录一下:

    from django.shortcuts import render,HttpResponse,redirect
    from django.contrib import auth
    
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            # user = models.User.objects.filter(username=username,password=password).first()
            user = auth.authenticate(request,username=username,password=password)
            if user:
                auth.login(request,user)
                # 这一句执行完之后,其他的视图函数可以直接通过request.user获取到当前用户对象
                # 这一句话就相当于操作session记录
                return HttpResponse('登录成功')
        return render(request,'login.html')
    
    
    def index(request):
        print(request.user)
        print(request.user.username)
        print(request.user.password)
        return HttpResponse('index')
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <p>password:<input type="text" name="password"></p>
        <input type="submit">
    </form>
    </body>
    </html>

    session可以记住登录状态,登录后可以直接查看index视图,如果跳转之前要确认登录可以加装饰器:

    在settings.py中配置一下,实现未登录跳转到登录页面:

    LOGIN_URL = '/login/'
    from django.contrib.auth.decorators import login_required
    @login_required
    def home(request): return HttpResponse('home') @login_required def xxx(request): return HttpResponse('xxx')

    接下来介绍一下注销:

    def logout(request):
         auth.logout(request)
         # 相当于request.session.flush()
         return HttpResponse('注销成功')

    刚才是用run manage.py task工具添加记录的,现在我们来自己注册:

    from django.shortcuts import render,HttpResponse,redirect
    from django.contrib import auth
    from django.contrib.auth.models import User
    
    def register(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            email = '111@qq.com'
            User.objects.create_user(username=username,password=password)
            # User.objects.create_superuser(username=username,password=password,email=email)
            # User.objects.create(username=username,password=password)  # 不要用,密码是明文
        return render(request,'register.html')
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <p>password:<input type="text" name="password"></p>
        <input type="submit">
    </form>
    </body>
    </html>

    我们现在来改一下密码:

    @login_required
    def set_password(request):
        """
        123是用户原来的密码
        456是用户修改的密码
        这里为了偷懒没有做前后获取密码操作
    
        """
        print(request.user.check_password('123'))
        if request.user.check_password('123'):
            request.user.set_password('456')
            request.user.save()  # 修改密码必须save保存.不然无效
        return HttpResponse('ok')

    如果你还想增加字段,那就要在models.py里进行操作了:

    settings.py:
    # 告诉django不再使用默认的auth_user表,而是使用我自己的模型表
    
    # AUTH_USER_MODEL = "app名.models里面对应的模型表名"
    AUTH_USER_MODEL = "app01.Userinfo"
    
    models.py:
    
    from django.db import models
    from django.contrib.auth.models import User,AbstractUser
    # Create your models here.
    
    # 一对一关联
    class UserDetail(models.Model):
      phone = models.CharField(max_length=11)
      user = models.OneToOneField(to=User)
    
    # 第二种方式
    class Userinfo(AbstractUser):
      phone = models.CharField(max_length=32)
      avatar = models.CharField(max_length=32)
  • 相关阅读:
    js 百度地图和谷歌地图的选择
    angular4 自定义表单验证Validator
    推荐20个很有帮助的 Web 前端开发教程
    前端同学大福利,最全的面试题目整理
    前端开发:如何写一手漂亮的 Vue
    推荐20个很有帮助的 Web 前端开发教程
    面试分享:一年经验初探阿里巴巴前端社招
    想成为一个高效的Web开发者吗?来看看大牛分享的经验吧~ #精选JAVASCRIPT前端开发
    初学者Web介绍一些前端开发中的基本概念用到的技术
    Web设计新手应知道的10个锦囊妙计
  • 原文地址:https://www.cnblogs.com/sima-3/p/11063885.html
Copyright © 2020-2023  润新知