auth模块

内容概要

  • csrf跨站请求伪造
  • csrf相关校验策略
  • CBV添加装饰器的多种方式
  • auth认证模块

csrf跨站请求伪造

钓鱼网站:模仿一个正规的网站 让哟ing胡在该网站上做操作 但是操作的结果会影响到用户正常的网站账户 但是其中有一些猫腻

模拟钓鱼网站案例:转账案例

原网站

def tans_func(request):
    if request.method == 'POST':
        user1 = request.POST.get('user1')
        user2 = request.POST.get('user2')
        money = request.POST.get('money')
        print('[%s]向[%s]转账[%s]' % (user1, user2, money))
    return render(request, 'tans.html')
<form action="" method="post">
    <p>转账人
        <input type="text" name="user1">
    </p>
    <p>收款人
        <input type="text" name="user2">
    </p>
    <p>转帐金额
        <input type="text" name="money">
    </p>

    <input type="submit">

钓鱼网站

def tans_func(request):
    return render(request, 'tans.html')
<form action="http://127.0.0.1:8000/tans/" method="post">
    <p>转账人
        <input type="text" name="user1">
    </p>
    <p>收款人
        <input type="text">
        <input type="text" name="user2" value="wewe" style="display: none">
    </p>
    <p>转账金额
        <input type="text" name="money">
    </p>
    <input type="submit">

</form>

csrf校验伪造

在提交数据的位置添加唯一标识

就是我们以前会注释的那个csrf那个中间件现在加了{%csef_token%}就可以不用注释

作用就是判断你是不是我自己的页面发送过来的请求,如果是就处理,不是就不处理

1.form表单csrf策略
	在form表单内部添加 {% csef_token %}

2.ajax请求
	方式1:自己动手取值 较为繁琐
    data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val(),},

就是拿到它的值

方式2:利用模板语法自动获取(一定要用引号引起来)
data:{'csrfmiddlewaretoken':'{{ csrf_token }}',},

方式3:直接引入一个js脚本即可(官方提供的)
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);
    }
  }
});

把这的写到js文件里面然后导入一下就可以了

csrf相关装饰器

整个django项目都校验csrf到那时某些视图函数\类不想校验

整个django项目都不想校验csrf但是某些视图函数\类需要校验

FBV添加装饰器的方式(与正常函数添加装饰器一样)

from django.views.decorators.csrf import csrf_exempt, csrf_protect
@csrf_protect  # 需要csrf 校验
def tans_func(request):
    if request.method == 'POST':
        user1 = request.POST.get('user1')
        user2 = request.POST.get('user2')
        money = request.POST.get('money')
        print('[%s]向[%s]转账[%s]' % (user1, user2, money))
    return render(request, 'tans.html')

不需要csrf校验

from django.views.decorators.csrf import csrf_exempt, csrf_protect


@csrf_exempt  # 不需要csrf 校验
def tans_func(request):
    if request.method == 'POST':
        user1 = request.POST.get('user1')
        user2 = request.POST.get('user2')
        money = request.POST.get('money')
        print('[%s]向[%s]转账[%s]' % (user1, user2, money))
    return render(request, 'tans.html')

CBV添加装饰器的方法

CBV添加装饰器的方法(与正常的情况不一样 需要注意)

方式一(单独生效)

from django import views
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt, csrf_protect

class MyClass(views.View):
    @method_decorator(csrf_protect)
    def post(self, request):
        user1 = request.POST.get('user1')
        user2 = request.POST.get('user2')
        money = request.POST.get('money')
        print('[%s]向[%s]转账[%s]' % (user1, user2, money))
        return render(request, 'tans.html')

    def get(self, request):
        return render(request, 'tans.html')

方式二(单独生效)

@method_decorator(csrf_protect, name='post')

只给这个类下面的post方法添加装饰器

方式三(全局生效)

@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
    pass

这是给这个类里面的所有方法都添加上装饰器

注意有一个装饰器是特例只能有一种添加方式

csrf_exempt

只有在dispatch方法中添加才会生效

auth认证模块

前戏:django自带一个admin路由 但是需要我们提供管理员账号和密码

如果想要使用admin后台管理 需要先创建表 然后创建管理员账号

直接执行数据库迁移命令即可默认的auth_user表 该表就是admin后台管理默认的认证表

  1. 创建超级管理员

    python38 manage.py createsuperuser

基于auth_user表编写用户相关的各项功能

​ 登录、校验用户是否登录、修改密码、注销登录等

auth认证相关模块及操作

  1. 注册User.object.create_user(username=username, password=password')

    from django.contrib import auth
    from django.contrib.auth.models import User
    def register_func(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            User.objects.create_user(username=user, password=pwd)
            return HttpResponse('注册成功')
        return render(request, 'register.html')
    

    他会自动给你加密

  2. 判断用户名和密码是否正确

    auth.authenticate(requser,username=username, password=password)

    登录成功后返回客户端登录凭证

    auth.login(request, user_obj)

    def login_func(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            # 1. 校验用户名和密码是否正确(不分开校验) 自己无法比对密码 必须使用auth模块
            user_obj = auth.authenticate(request, username=user, password=pwd)
            if user_obj:
                print(user_obj, type(user_obj))
                print(user_obj.username, type(user_obj.username))
                # 2.用户登录成功(返回给客户端登录凭证,随机字符串)
                auth.login(request, user_obj)
                return HttpResponse('登录成功')
            else:
                return HttpResponse('用户名或密码错误')
        return render(request, 'login.html')
    

  3. 判断用户是否登录

    request.user.is_authenticated

    def home_func(request):
        if request.user.is_authenticated:
            print(request.user.is_authenticated)
            return HttpResponse('这是home页面')
        else:
            return redirect('/login/')
    

    返回的是一个布尔值

  4. 获取登录用户对象数据

    request.user

    def home_func(request):
        # 获取当前登录用户
        print(request.user)
        print(request.user.username)
        return HttpResponse('这是home页面')
    

  5. 校验用户是否登录装饰器

    from django.contrib.auth.decorators import login_required
    @login_required(login_url='/login/')
    
        @login_required						全局配置
     	 配置文件中LOGIN_URL = '/login/'
    
    from django.contrib.auth.decorators import login_required
    
    
    # 如果没有登录则跳转到 /login/
    @login_required(login_url='/login/')  # 局部配置
    def home_func(request):
        return HttpResponse('这是home页面')
    

  6. 校验原密码是否正确

    request.user.check_password(原密码)

    修改密码

    request.user.set_password(新密码)
    requser.user.save()
    
    @login_required(login_url='/login/')
    def set_password_func(request):
        if request.method == 'POST':
            old_pwd = request.POST.get('old_pwd')
            new_pwd = request.POST.get('new_pwd')
            # 判断原密码是否正确
            if request.user.check_password(old_pwd):
                # 修改密码
                request.user.set_password(new_pwd)
                # 写入数据库
                request.user.save()
                return HttpResponse('修改密码成功')
            else:
                return HttpResponse('原密码错误')
        return render(request, 'setPassword.html')
    

  7. 退出登录

    auth.logout(request)

    也就是把那条标识登录的cookie给删除了

扩展auth_user表

还想使用auth模块的功能 并且又想扩展auth_user表的字段

思路1:一对一字段关联

思路2:替换auth_user

​ 步骤1:模型层编写模型类继承AbstractUser

from django.contrib.auth.models import AbstractUser


class UserInfo(AbstractUser):
    phone = models.CharField(max_length=11, null=True)
    desc = models.CharField(max_length=32, null=True)

步骤2:一定要在配置文件中声明替换关系

AUTH_USER_MIDEL = 'app01.UserInfo'

ps:替换还有一个前提 就是数据库迁移没有执行过(auth相关表没有创建)

posted @ 2022-12-28 16:14  可否  阅读(26)  评论(1编辑  收藏  举报