目录
csrf跨站请求伪造
钓鱼网站:模仿一个正规的网站 让用户在该网站上做操作 但是操作的结果会影响到用户正常的网站账户 但是其中有一些猫腻
eg:英语四六级考试需要网上先缴费 但是你会发现卡里的钱扣了但是却交到了一个莫名其妙的账户 并不是真正的四六级官方账户
其实就是钓鱼网站:
模仿一个正规的网站 让用户在该网站上做操作
案例:模仿钓鱼网站
如图
简单的页面获取
这样就就可以正常的转账
再创建一个Django项目 一模一样路由也一样的
在假网站上修改提交的位置
如图:用户所看的是上面的 而发送的的其实是下面的
在假网站上操作转账
真网站的后台收到的打印结果
那么如何区分真假网站发送的请求?
别人网站发送的正真请求是从自己网站发送过来的还是从别人的钓鱼网站发送过来的
如果真正的网站能够区分出来的就可以避免钓鱼的发生
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中就有添加检验唯一标识检验唯一标识
如何在返回的页面上添加唯一标识 在提交数据的位置添加唯一标识???
1.form表单csrf策略
form表单内部添加 {% csrf_token %}
就有模板语法提供了 只要在表单内部就会跟随着form表单数据的提交到Django后端校验
如图到页面会发现多了个input框并且隐藏了,键name:csrfmiddlswaretoken、值value:就是产生的唯一标识
而且是自动产生的唯一标识 每提交刷新一次就变 保证了数据的时效性
2.ajax请求csrf策略
Ajax会不会检验csrf呢?
如图朝服务端发送数据检验csrf,数据里就必须要携带csrf相关的键值对,如果发送的是空的,没有csrf相关的东西,就无法通过csrf的校验
那么就有三种添加方式
方式一:
如图,自己添加键值对,较为繁琐
方式二:
利用模板语法自动获取,它是一个字符串一定要用引号引起来
那如果在前后端分离可能没有模板语法的功能
方式三
直接引入js脚本
首先在静态文件里新建js文件
如图js代码就是自动帮你处理csrf相关操作的
引入js文件,导入该配置文件之前,需要先导入jQuery 这样就可以发送了
将下面的文件配置到你的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校验
但是呢有特例,有两种特殊情况
第一种情况
就整个Django项目都校验csrf 但是某些个视图函数/类不校验
第二种情况
整个Django项目不校验 但是呢某些视图函数/类需要校验
这两种情况是可以实现的 就有csrf提供的装饰器
FBV中添加装饰器的方式
导模块
如图此时全局是校验csrf的
那么如下图在视图函数中添加了csrf的装饰器 就是忽略csrf的校验
反过来 全局不校验时
但是就想某些视图函数校验 加上csrf装饰器
CBV添加的方式
与正常情况不一样
方式一
单独生效,得要借助于一个模块,在函数上添加装饰器
方式二
指名道姓有效,在类名上面添加装饰器
方式三
整个类中有效 因为dispath是对方法做分发的
注意:
有一个装饰器是特例只能有一种添加方式>>>:csrf_exempt
只有在dispatch方法添加才会生效
auth认证模块
前戏:
Django自带一个admin路由 但是要我们提供管理员账号、密码
那从哪来?
如果想要使用admin后台管理 需要先创建表 然后创建管理员账号密码,直接执行数据库迁移命令即可产生默认的auth_user表,该表就是admin后台管理默认的认证表
但是,表可以是不需要咱们自己创,只需要执行了迁移命令,会自动生成
跟用户相关的表,就是admin后台管理的认证表
新的命令:python38 manage.py createsuperuser
怎么创建一个新的Django后台管理员账号
按照提示去创建用户名或密码,邮箱可以不输
会出现一个提示,提醒你密码是明文展示的,再让你重复确认
如果密码设的太简单了,还会提醒你密码过于简单
1就表示你是超级管理员,0表示不是
这样注册的用户名和密码就能登入了
终端默认只能创管理员,普通用户只能用业务逻辑创
需求:
基于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)
路由层
视图函数
HTML
后端拿到返回的用户名及密码,再校验用户名是否已存在,可是模型表里又是空的 没法用models点了
那么就有auth模块,需要导入一个模块
auth.authenticate这个方法必须传用户名和密码的才能够认证,所以要单看用户名是否已存在用auth模块是不行滴
还需要再到一个User模块,把User看成是一个表名,这样跟ORM的操作就差不多了,判断返回值是否有值,这样就可以校验用户是否已存在了
用户注册功能
再接下来注册用户,自己去注册的话,密码存进去的就是明文的,而之后要用到auth模块提供的方法时auth模块是会自动加密的,一个是加密的一个明文这样一来就无法比对
得用create_user 自动给密码加密在存到表里去
用户登入
路由
HTML
后端
判断用户名和密码是否正确
校验用户名和密码 用户输入的是明文的密码而存在表里的是加密之后的密码 这样就无法比对密码 这就得使用auth提供的方法
打印返回值res,返回的是用户对象,而输错了返回的是none
用户对象再去点它的用户名及密码,如图就可以拿到用户名及加密的字符串密码了
这样就可以判断auth.authenticate方法的返回值是否有值来判断用户名和密码是否输入正确。
那么在用户登入成功了就得给用户返回一个登入了的cookie数据凭证,这也不需要我们自己操作只需要用到auth模块
auth.login
会自动操作Django中的session表
自动帮你去Django_session表里面自动创建一个键值对,然后把用户对象存到表里面 再返回给前端浏览器一个随机字符串
如下图
session_data加密的就是用户对象
如下图只要在完成auth.login这个方法之后,这个方法执行之后就相当于用户已经是登入成功过了
获取登录用户对象数据
在视图函数里面的任意位置用request.user都可以拿到当前登入的用户名
而假如没有登入,request.user拿的就是一个匿名用户
判断用户是否登录
显示效果
实例:
模仿博客园:
当你没有登入的时候显示注册 登入,当你登入了的时候显示你的名字
这时request.user它还支持可以继续is_authenticate方法,判断用户对象是否已登入
如图登入了打印True,没有登入打印False
前端:
简单的模拟实现博客园用户登入与用户未登入时的显示
这样只要用户登入了就显示当前用户名,没有登入就显示注册 登入
校验用户是否登录装饰器
index页面只有登入的用户才能看
因为是要已经登入过的用户才能才能看,在auth表里装饰器也写好了,也有现成的
该装饰器可以自定义控制 ,当用户如果没有登入想要访问只有登入了才能看的视图函数就能让它跳到某一个路由去
局部配置
只要用户没有登入就可以指定路由跳转到哪个地址 自定义程度高
如图:
全局配置
很多时候用户在没有登入的时候,都是跳转到登入login页面,在配置文件中加
视图函数装饰器就不用再加括号了
统一全局配置
再到用户去修改密码了
判断原密码是否正确
用request.user.check_password(原密码)会有一个返回值
如图,原密码正确返回True 不正确none
用户修改密码
修改密码用request.user.set_password(新密码),之后一定要保存否则不会修改request.user.save()
注销登入
就是把客户端用来表示自己身份的cookie数据删掉就好了
或者把服务端session表里面的数据删掉
拓展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表中的的字段,如:用户的手机号 个人简介等
思路一:
一对一字段关联
新创一张模型表做一对一关联可以直接在新创的模型表里添加一些新的字段,两个表里的数据都是一一对应的,之后再基于正反向查询就相当于扩展了字段
思路二:
直接替换auth_user表
user表继承了Abstractuser
再执行迁移命令的时候会报错,替换还有一个前提 就是数据库迁移没有执行过(auth相关表没有创建),
要确保没有执行过数据库迁移命令
现在我们原来的库就不行了已经产生了auth_user表,必须要一个全新的库
我们把原有表删除和注册信息删除
注册记录也删除
之后再配置文件中加上 AUTH_USER_MODEL = 'app01.UserInfo'
再执行数据库迁移命令
如图在auth_user表中就有新增的字段了
标签:登入,模块,用户,校验,auth,认证,user,csrf From: https://www.cnblogs.com/xiao-fu-zi/p/17004591.html