首页 > 其他分享 >csrf校验策略 csrf相关装饰器 auth认证模块 auth_user表扩展

csrf校验策略 csrf相关装饰器 auth认证模块 auth_user表扩展

时间:2022-12-26 22:55:07浏览次数:61  
标签:登录 校验 auth 用户 user csrf

目录

csrf跨站请求伪造

钓鱼网站:模仿一个正规的网站 让用户在该网站上做操作 但是操作的结果会影响到用户正常的网站账户 但是其中有一些猫腻
	eg:英语四六级考试需要网上先缴费 但是你会发现卡里的钱扣了但是却交到了一个莫名其妙的账户 并不是真正的四六级官方账户
        
模拟钓鱼网站案例:转账案例
	内部隐藏标签
 
思考:作为网站的开发者如何区分真假网站页面发送的请求

img

了解更多:https://blog.csdn.net/qq_45803593/article/details/124727762

csrf校验策略

我们的网站无法识别哪些请求自己内部的页面发送过来的,哪些请求是钓鱼网站发过来的。
解决办法:在提交数据的位置添加唯一标识

1.form表单csrf策略

form表单内部添加 {% csrf_token %}

示例:
image-20221225164438013

查看表单的变化:

image-20221225164638574

每次刷新时这个value值都会变化。后端通过这个唯一标识,来区分真网站和钓鱼网站。

2.ajax请求csrf策略

csrf会导致ajax请求无法发送。

点击按钮发送ajax请求:
image-20221225165249155

无法通过crsf校验:
image-20221225165622419

你只要朝服务端发请求,请求里就必须含有crsf相关的键值对。

方式1:标签查找

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

通过标签查找,获取{% csrf_token %}产生的标签的value值:

image-20221225170021965

方式2:利用模板语法自动获取

   data:{ 'csrfmiddlewaretoken':'{{ csrf_token }}','username':'jason'},
    
'''注意:一定要用引号引起来'''

示例:

image-20221225170504818

方式3:引入官网js脚本

当前后端分离时,没有模板语法,所以可以使用官网js脚本。
在django静态文件里,添加如下js脚本:

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);
    }
  }
});

在页面上把这个静态文件加载过来即可(脚本名字可以自定义):
image-20221225171528059

csrf相关装饰器

在使用csrf校验时,我们可能会遇到如下两种需求:

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

这时候可以给视图函数、视图类添加装饰器来实现需求。

FBV添加装饰器的方式

与正常函数添加装饰器一致。

from django.views.decorators.csrf import csrf_exempt, csrf_protect
# @csrf_exempt
@csrf_protect
def transfer_func(request):pass

csrf_protect装饰的函数,添加crsf校验。
csrf_exempt装饰的函数,免除crsf校验。

CBV添加装饰器的方式

与正常情况不一样 需要注意。需要额外导入method_decorator
主要有三种方式:

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

# @method_decorator(csrf_protect, name='post')  # 方式2:单独生效
class MyView(views.View):
    @method_decorator(csrf_protect)  # 方式3:整个类中生效
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    # @method_decorator(csrf_protect)  # 方式1:单独生效
    def post(self, request):
        return HttpResponse('from cbv post view')
  
 CBV添加装饰器时,注意有一个装饰器是特例只能有一种添加方式>>>:csrf_exempt
 	只有在dispatch方法添加才会生效

方式1:装饰类中方法

对被装饰的方法单独生效。
image-20221225174045232

这里表示对post请求添加csrf校验。

方式2:装饰整个类

装饰整个类时,需要传入参数,申明装饰的是类中哪个方法,是需要添加csrf校验,还是免除csrf校验。

image-20221225174349013

这里还是对post请求添加csrf校验。

方式3:装饰dispatch方法

我们在自己的视图类中,写一个dispatch方法,再使用super调用父类的dispatch,最后给dispatch方法添加装饰器。
装饰dispatch方法时,会对类中所有方法生效。

image-20221225174801064

这里表示对视图类中所有方法都添加csrf校验。

特例 csrf_exempt

在全局crsf校验打开的情况下:我们想让我们的CBV不校验crsf。

image-20221225175801997

如下图所示:csrf_exempt只有在dispatch方法添加才会生效

image-20221225175708635

auth认证模块前戏

django后台管理功能

前戏:django自带一个admin路由 但是需要我们提供管理员账号和密码
如果想要使用admin后台管理 需要先创建表 然后创建管理员账号
直接执行数据库迁移命令即可产生默认的auth_user表 该表就是admin后台管理默认的认证表
1.创建超级管理员
	python38 manage.py createsuperuser

基于auth_user表编写用户相关的各项功能
	登录、校验用户是否登录、修改密码、注销登录等

第一次迁移数据库之后会自动创建auth_user表:
image-20221225181101123

该表就是admin后台管理默认的认证表

创建超级管理员

python38 manage.py createsuperuser

示例:
image-20221225181539306

创建完之后查看auth_user表:
image-20221225181642145

1表示该用户是超级管理员。
管理员的密码经过了加密。

使用该账号登录django后台管理:
image-20221225181734355

不仅可以创建超级管理员,还可以创建普通用户。
只不过使用终端只允许你创建超级管理员,只能用业务逻辑的形式创建普通用户。

auth认证相关模块及操作

from django.contrib import auth
from django.contrib.auth.models import User
1.用户注册功能
    User.objects.create_user(username=username, password=password)
2.判断用户名和密码是否正确
	user_obj = auth.authenticate(request,
                       username=username,
                       password=password)  
3.判断用户是否登录
	request.user.is_authenticated
4.获取登录用户对象数据
	request.user
5.校验用户是否登录装饰器
	from django.contrib.auth.decorators import login_required
    @login_required(login_url='/login/')  局部配置 
    @login_required						全局配置
 	 配置文件中LOGIN_URL = '/login/'
6.校验原密码是否正确
	request.user.check_password(原密码)
7.修改密码
	request.user.set_password(新密码)
 	request.user.save()
8.退出登录
	auth.logout(request)

用户注册

前端页面:
image-20221225185339549

视图函数:

先导入auth模块,使用auth.authenticate方法

image-20221225185551511

这里是只传入了用户名。必须要传入用户名和密码。

导入auth_user表:
image-20221225190608111

使用create方法注册用户:

image-20221225190743422

查看auth_user表:

image-20221225190837449

此时密码没有进行加密。

使用create_user方法:
image-20221225191050964

会对密码进行加密:
image-20221225191035858

用户登录

登录时,用户输入的是密码明文,而我们的auth_user表存储的是加密的密码,所以无法进行正常比对,需要经过auth模块的方法比对:

image-20221225194329548

当用户名和密码输入正确时,auth.authenticate方法会返回用户对象,输入不正确时返回None:
image-20221225210618486

登录成功后,给客户端返回加密字符串:
image-20221225211321128

auth.login: 会自动去django_session表里创建一个键值对,然后把用户对象存在这个表里面,最后返回给前端浏览器一个加密字符串。

查看session表:

image-20221225211514114

request.user获取当前登录的用户对象数据:
image-20221225211654006

对于没有登录的用户:
image-20221225211945445

request.user会拿到匿名用户。

网站首页效果

需求:已经登录的用户,显示用户的名字。用户未登录,显示登录注册。

判断当前用户对象是否已登录:

image-20221225222248300

这个方法可以判断当前的请求是否已经登录。

前端页面:
image-20221225222446146

校验用户登录的装饰器

示例:
被login_required装饰的函数,只有登录的用户(携带cookies)才能查看。

image-20221225232114481

没有登录的用户,访问会跳转到登录页面:
只不过这个登录页面的路由,是别人写好的,但是我们也可以自定义这个路由。
image-20221225233008298

控制跳转的路由:
image-20221225233307070

可以让不同的视图函数跳转到不同的页面。

当视图函数特别多的情况下:
login_url='/login/'这行代码会反复写。还可以进行优化。
可以在setting文件中,写一个全局配置:

image-20221225233603577

这里的意思是:如果使用login_required装饰视图函数不指定跳转的路由,就使用配置文件中指定的路由LOGIN_URL

如果全局和局部都指定了路由,那么会跳转到哪个路由?
这种情况下会跳转到局部指定的路由。

用户修改密码

视图函数:
image-20221225234132014

登录的用户才能修改密码。
前端页面:

image-20221225234221020

视图函数:
image-20221225234352299

获取到的原密码是明文的,auth_user表里存储的密码是密文的,我们无法比较。此时用户已经登录,所以我们可以用request.user拿到用户数据对象。

使用request.user对象的方法校验密码:
image-20221225234848819

用户注销登录

视图函数:
image-20221225235152478

会自动把浏览器存储的cookies、auth表里存储的用户数据删除。

auth_user表扩展

还想使用auth模块的功能 并且又想扩展auth_user表的字段
思路1:一对一字段关联
思路2:替换auth_user表
	步骤1:模型层编写模型类继承AbstractUser
   		from django.contrib.auth.models import AbstractUser
       class UserInfo(AbstractUser):
        # 填写AbstractUser表中没有的字段
        phone = models.BigIntegerField()
        desc = models.TextField()
 	步骤2:一定要在配置文件中声明替换关系
        AUTH_USER_MODEL = 'app01.UserInfo'
	ps:替换还有一个前提 就是数据库迁移没有执行过(auth相关表没有创建)

问题:我们想使用django生成的auth_user表,但是又觉得这个表的字段不够多。

如何给auth_user表扩展更多的字段?

思路1:一对一字段关联

在model再建模型表:

image-20221226000053712

我们的表的数据和auth_user表的数据一一对应。

思路2:替换auth_user表(重要)

首先在模型层导入真正的auth_user表:
image-20221226000311835

我们之前导入的User,继承于AbstractUser。

所以我们写一个模型类,继承于AbstractUser:
所以我们可以在继承了auth_user表的基础上,进行扩展。
注意不要填写已有的字段,会冲突。
image-20221226000551611

注意:一旦我们写了一个模型类,继承了AbstractUser,就相当于要替换django自动生成的auth_user表,取而代之的是我们的表(userinfo)

想这么做的话,要确保我们没有执行过数据库迁移命令,必须保证使用的是一个全新的库。不可以使用已经产生过auth_user表的数据库。

并且还要在配置文件中加一句话:
image-20221226001103462

示例:

image-20221226001208678

之后所有基于auth_user表的操作,都会使用我们创建的这张表。

练习

1.利用auth模块编写一个网站导航条相关的功能(用自己创建的表)
	也可以直接在图书管理系统中切入用户相关的功能
		导航条右侧 用户没有登录现实 登录 和 注册
       用户登录之后 现实当前用户名及登录之后的一些操作 修改密码 退出登录

标签:登录,校验,auth,用户,user,csrf
From: https://www.cnblogs.com/passion2021/p/17007107.html

相关文章