首页 > 其他分享 >cs跨站请求伪造 csrf添加装饰器的多种方式 auth认证模块 auth认证相关模块及操作 拓展auth_user表

cs跨站请求伪造 csrf添加装饰器的多种方式 auth认证模块 auth认证相关模块及操作 拓展auth_user表

时间:2022-12-25 21:26:41浏览次数:35  
标签:登入 模块 用户 校验 auth 认证 user csrf

目录

csrf跨站请求伪造

钓鱼网站:模仿一个正规的网站 让用户在该网站上做操作 但是操作的结果会影响到用户正常的网站账户 但是其中有一些猫腻
	eg:英语四六级考试需要网上先缴费 但是你会发现卡里的钱扣了但是却交到了一个莫名其妙的账户 并不是真正的四六级官方账户

其实就是钓鱼网站:

模仿一个正规的网站 让用户在该网站上做操作

案例:模仿钓鱼网站

如图

简单的页面获取

image

这样就就可以正常的转账

image

再创建一个Django项目 一模一样路由也一样的

image

在假网站上修改提交的位置

image

如图:用户所看的是上面的 而发送的的其实是下面的

image

在假网站上操作转账

image

真网站的后台收到的打印结果

image

那么如何区分真假网站发送的请求?

别人网站发送的正真请求是从自己网站发送过来的还是从别人的钓鱼网站发送过来的

如果真正的网站能够区分出来的就可以避免钓鱼的发生

csrf相关校验策略

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

1.form表单csrf策略
	form表单内部添加 {% csrf_token %}
2.ajax请求csrf策略
	// 方式1:自己动手取值 较为繁琐
   {#data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
   // 方式2:利用模板语法自动获取(一定要用引号引起来)
   {#data:{ 'csrfmiddlewaretoken':'{{ csrf_token }}','username':'jason'},#}
   // 方式3:直接引入一个js脚本即可(官网提供的)
 	参考:https://www.cnblogs.com/Dominic-Ji/p/9234099.html

原理:

真网站在给用户发送一些比较核心的页面 那么会在页面上添加一个唯一标识

然后等这个页面向我发请求的时候会先检验这个页面有没有这个标识 如果没有就说明这个页面根本不是之前给的页面 就会把你直接拒绝掉

在Django中就有添加检验唯一标识检验唯一标识

image

如何在返回的页面上添加唯一标识 在提交数据的位置添加唯一标识???

1.form表单csrf策略

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

就有模板语法提供了 只要在表单内部就会跟随着form表单数据的提交到Django后端校验

image

如图到页面会发现多了个input框并且隐藏了,键name:csrfmiddlswaretoken、值value:就是产生的唯一标识

image

而且是自动产生的唯一标识 每提交刷新一次就变 保证了数据的时效性

2.ajax请求csrf策略

Ajax会不会检验csrf呢?

如图朝服务端发送数据检验csrf,数据里就必须要携带csrf相关的键值对,如果发送的是空的,没有csrf相关的东西,就无法通过csrf的校验

image
image

那么就有三种添加方式

方式一:

如图,自己添加键值对,较为繁琐

image

方式二:

利用模板语法自动获取,它是一个字符串一定要用引号引起来

image

那如果在前后端分离可能没有模板语法的功能

方式三

直接引入js脚本

首先在静态文件里新建js文件

image

如图js代码就是自动帮你处理csrf相关操作的

image

引入js文件,导入该配置文件之前,需要先导入jQuery 这样就可以发送了

image

将下面的文件配置到你的Django项目的静态文件中,在html页面上通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的)

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添加装饰器的多种方式

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

FBV添加装饰器的方式(与正常函数添加装饰器一致)
from django.views.decorators.csrf import csrf_exempt, csrf_protect
# @csrf_exempt
@csrf_protect
def transfer_func(request):pass

CBV添加装饰器的方式(与正常情况不一样 需要注意)
主要有三种方式
# @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')
  
注意有一个装饰器是特例只能有一种添加方式>>>:csrf_exempt
 	只有在dispatch方法添加才会生效

配置文件中,把这行打开,意味着只要你发post请求就都要校验csrf校验

image

但是呢有特例,有两种特殊情况

第一种情况

就整个Django项目都校验csrf 但是某些个视图函数/类不校验

第二种情况

整个Django项目不校验 但是呢某些视图函数/类需要校验

这两种情况是可以实现的 就有csrf提供的装饰器

FBV中添加装饰器的方式

导模块

image

如图此时全局是校验csrf的

image

那么如下图在视图函数中添加了csrf的装饰器 就是忽略csrf的校验

image

反过来 全局不校验时

image

但是就想某些视图函数校验 加上csrf装饰器

image

CBV添加的方式

与正常情况不一样

方式一

单独生效,得要借助于一个模块,在函数上添加装饰器

image-20221224224239810

方式二

指名道姓有效,在类名上面添加装饰器

image

方式三

整个类中有效 因为dispath是对方法做分发的

image

注意:

有一个装饰器是特例只能有一种添加方式>>>:csrf_exempt
只有在dispatch方法添加才会生效

auth认证模块

前戏:

Django自带一个admin路由 但是要我们提供管理员账号、密码
那从哪来?

如果想要使用admin后台管理 需要先创建表 然后创建管理员账号密码,直接执行数据库迁移命令即可产生默认的auth_user表,该表就是admin后台管理默认的认证表

但是,表可以是不需要咱们自己创,只需要执行了迁移命令,会自动生成

image

跟用户相关的表,就是admin后台管理的认证表

image

新的命令:python38 manage.py createsuperuser

怎么创建一个新的Django后台管理员账号

image

按照提示去创建用户名或密码,邮箱可以不输

会出现一个提示,提醒你密码是明文展示的,再让你重复确认

image

如果密码设的太简单了,还会提醒你密码过于简单

image

1就表示你是超级管理员,0表示不是

这样注册的用户名和密码就能登入了

image

终端默认只能创管理员,普通用户只能用业务逻辑创

需求:

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

author认证相关模块及操作

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

视图函数

image

HTML

image

后端拿到返回的用户名及密码,再校验用户名是否已存在,可是模型表里又是空的 没法用models点了

那么就有auth模块,需要导入一个模块

image

auth.authenticate这个方法必须传用户名和密码的才能够认证,所以要单看用户名是否已存在用auth模块是不行滴

image

还需要再到一个User模块,把User看成是一个表名,这样跟ORM的操作就差不多了,判断返回值是否有值,这样就可以校验用户是否已存在了

image

用户注册功能

再接下来注册用户,自己去注册的话,密码存进去的就是明文的,而之后要用到auth模块提供的方法时auth模块是会自动加密的,一个是加密的一个明文这样一来就无法比对

image

得用create_user 自动给密码加密在存到表里去

image

用户登入

路由

image

HTML

image

后端

image

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

校验用户名和密码 用户输入的是明文的密码而存在表里的是加密之后的密码 这样就无法比对密码 这就得使用auth提供的方法

image

打印返回值res,返回的是用户对象,而输错了返回的是none

image

用户对象再去点它的用户名及密码,如图就可以拿到用户名及加密的字符串密码了

image

这样就可以判断auth.authenticate方法的返回值是否有值来判断用户名和密码是否输入正确。

那么在用户登入成功了就得给用户返回一个登入了的cookie数据凭证,这也不需要我们自己操作只需要用到auth模块

auth.login

会自动操作Django中的session表

image

自动帮你去Django_session表里面自动创建一个键值对,然后把用户对象存到表里面 再返回给前端浏览器一个随机字符串

image

如下图

session_data加密的就是用户对象

image

如下图只要在完成auth.login这个方法之后,这个方法执行之后就相当于用户已经是登入成功过了

image

获取登录用户对象数据

在视图函数里面的任意位置用request.user都可以拿到当前登入的用户名

image

而假如没有登入,request.user拿的就是一个匿名用户

image

判断用户是否登录

显示效果

实例:

模仿博客园:

当你没有登入的时候显示注册 登入,当你登入了的时候显示你的名字

image

这时request.user它还支持可以继续is_authenticate方法,判断用户对象是否已登入

image

如图登入了打印True,没有登入打印False

image

前端:

简单的模拟实现博客园用户登入与用户未登入时的显示

image

这样只要用户登入了就显示当前用户名,没有登入就显示注册 登入

校验用户是否登录装饰器

index页面只有登入的用户才能看

image

因为是要已经登入过的用户才能才能看,在auth表里装饰器也写好了,也有现成的

image

该装饰器可以自定义控制 ,当用户如果没有登入想要访问只有登入了才能看的视图函数就能让它跳到某一个路由去

局部配置

只要用户没有登入就可以指定路由跳转到哪个地址 自定义程度高

如图:

image

全局配置

很多时候用户在没有登入的时候,都是跳转到登入login页面,在配置文件中加

视图函数装饰器就不用再加括号了

image

统一全局配置

image

再到用户去修改密码了

image

判断原密码是否正确

用request.user.check_password(原密码)会有一个返回值

如图,原密码正确返回True 不正确none

image

用户修改密码

修改密码用request.user.set_password(新密码),之后一定要保存否则不会修改request.user.save()

image

注销登入

就是把客户端用来表示自己身份的cookie数据删掉就好了

或者把服务端session表里面的数据删掉

image

拓展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相关表没有创建)

想拓展auth_user表中的的字段,如:用户的手机号 个人简介等

思路一:

一对一字段关联

image

新创一张模型表做一对一关联可以直接在新创的模型表里添加一些新的字段,两个表里的数据都是一一对应的,之后再基于正反向查询就相当于扩展了字段

思路二:

直接替换auth_user表

image

user表继承了Abstractuser

image

image

再执行迁移命令的时候会报错,替换还有一个前提 就是数据库迁移没有执行过(auth相关表没有创建),

要确保没有执行过数据库迁移命令

现在我们原来的库就不行了已经产生了auth_user表,必须要一个全新的库

image

我们把原有表删除和注册信息删除

image

注册记录也删除

image

之后再配置文件中加上 AUTH_USER_MODEL = 'app01.UserInfo'

image

再执行数据库迁移命令

image

如图在auth_user表中就有新增的字段了

image

标签:登入,模块,用户,校验,auth,认证,user,csrf
From: https://www.cnblogs.com/xiao-fu-zi/p/17004591.html

相关文章