五十一、csrf跨站请求伪造和auth认证模块

一 csrf操作

<h1>这是假的网页</h1>
<form action="http://127.0.0.1:8000/bank/" method="post">
    <p>用户名:
        <input type="text" name="username">
    </p>
    <p>转账账户名:
        <input type="text"></p>
        <input type="text" name="name" value="jasper" style="display: none"></p>
    <p>
        转账金额:
        <input type="text" name="money">
    </p>
    <input type="submit">
</form>
<h1>这是真实的网页</h1>
<form action="" method="post">
    <p>用户名:
        <input type="text" name="username">
    </p>
    <p>转账账户名:
        <input type="text" name="name"></p>
    <p>
        转账金额:
        <input type="text" name="money">
    </p>
    <input type="submit">
</form>

一个服务端的post请求向另一个服务端发送。

二 在form表单中设置csrf

<form action="" method="post">
    {% csrf_token %}
    <p>用户名:
        <input type="text" name="name">
    </p>
    <p>密码:
        <input type="text" name="password">
    </p>
    <p>
        <input type="submit">
    </p>
</form>

{% csrf_token %}标签实际上就是在前端form表单中生成了一个隐藏域,name属性为csrfmiddlewaretoken,value属性时csrf校验的值。
在这里插入图片描述

三 ajax设置csrf

方式一:
通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送过去。

$.ajax({
	url:'',
	type:'post'
	data:{"name":"jasper", 
			"csfrmiddlewaretoken": $("[name="csfrmiddlewaretoken"]").val()}
	success: function(){

	}	
})

方式二:

**$.ajax({
	url:'',
	type:'post'
	data:{"name":"jasper", 
			"csfrmiddlewaretoken": $("{{ csrf_token }}"}
	success: function(){

	}	
})**

方式三:

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

当整个网站默认都不校验csrf,或者整个网站默认全部都校验,怎样可以让局部变得不同。

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

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

@csrf_exempt  # 免除校验
def index(request):
	return HttpResponse('index')

针对CBV不能直接在方法上添加装饰器,需要借助朱门添加装饰器的方法。

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


# @method_decorator(csrf_protect, name='post')  # 方式二:类名上装
# @method_decorator(csrf_exempt, name='post')  # 方式二:类名上装
class MyHome(views.View):
    # @method_decorator(csrf_protect)  # 方式三:装饰dispatch 全局添加
    @method_decorator(csrf_exempt)  # 方式三:装饰dispatch 全局添加
    def dispatch(self, request, *args, **kwargs):
        return super(MyHome, self).dispatch(request, *args, **kwargs)

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

    # @method_decorator(csrf_protect)  # 方式一:指名道姓
    # @method_decorator(csrf_exempt)  # 方式一:无效
    def post(self, request):
        print(request)
        return HttpResponse('Home post')

五 auth认证模块

django在执行数据库迁移命令后会创建一张auth_user表,该表可以配合auth模块做用户相关的功能:注册、登录、修改密码。注销等。

在terminal终端创建超级用户,创建完成即可登录。

python manage.py createsuperuser

5.1 auth模块常见功能

  1. 创建用户
    from django.contrib.auth.models import User
    # 创建普通用户
    User.objects.create_user()  # (self, username, email=None, password=None, **extra_fields)
    # 创建超级用户
    User.objects.create_superuser()  # self, username, email=None, password=None, **extra_fields
    
  2. authenticate()
    用户认证功能,认证成功返回一个用户对象,不成功返回None
    def auth_test(request):
    if request.method == 'POST':
        username = request.POST.get('name')
        password = request.POST.get('password')
        res = auth.authenticate(username=username, password=password)
        print(res, type(res))  # xuxiaoxu <class 'django.contrib.auth.models.User'>
    return render(request, 'auth_test.html')
    
  3. login()
    该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。
    def auth_test(request):
    if request.method == 'POST':
        username = request.POST.get('name')
        password = request.POST.get('password')
        res = auth.authenticate(username=username, password=password)
        if res:
            auth.login(request, res)
            print('登陆成功')
    return render(request, 'auth_test.html')
    
  4. logout()
    当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
    auth.logout(request)
    
  5. is_authenticated()
    用来判断是否通过了认证
    request.user.is_authenticated()
    
  6. 获取登录用户对象
    request.user
    
  7. 校验用户登录装饰器
    from django.contrib.auth.decorators import logig_required
    
    # login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None)
    
    # 'login_url':  该参数指定没有登录时跳转的地址,一般跳转到登录界面
    
    全局配置需要在settings.py中添加一句代码
    LOGIN_URL = '/login/'
    
  8. 校验密码是否正确
    request.user.check_password()
    
  9. 修改密码
    request.user.set_password()
    request.user.save()
    

5.2 auth_user表切换

在models.py中新创建一张表,继承AbstractUser,在表中添加auth表中没有的字段。

from django.db import models

# Create your models here.

from django.contrib.auth.models import AbstractUser


class UserInfo(AbstractUser):
    phone = models.BigIntegerField()

在settings.py中配置

AUTH_USER_MODEL = 'app01.UserInfo'

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值