csrf
简介
1.csrf跨站请求伪造:
1.1 如钓鱼网站:假设有一个和银行网页一模一样的网址页面 用户在该页面操作转账
结果:钱减少 转账人未收到钱 转账到另一个不知道的账户上
1.2 原因:提供给用户填写转账用户的input表单为无效表单 真正有效的表单被隐藏了
1.3 预防:
csrf策略:通过在返回的页面上添加独一无二的标识信息从而区分正规网站与钓鱼网站
1.4 实操:一台计算机上两个服务端不同端口启动 钓鱼网站提交的地址改为正规的网址
真网站路由层代码:假网站一致
urlpatterns = [
path('admin/', admin.site.urls),
path('func/', views.func),
]
真网站视图层代码:假网站一致
def func(request):
if request.method == 'POST':
username = request.POST.get('username')
target_name = request.POST.get('target_name')
money = request.POST.get('money')
print(f'{username}给{target_name}转账{money}')
return render(request, 'func.html')
真网站模板层代码:
<h1>真网站</h1>
<form action="" method="post">
<p>username:
<input type="text" name="username"></p>
<p>target_name:
<input type="text" name="target_name">
</p>
<p>money:
<input type="text" name="money">
</p>
<p>
<input type="submit">
</p>
</form>
假网站模板层代码:
<h1>钓鱼网站</h1>
<form action="http://127.0.0.1:8000/func/" method="post"> # 向真的系统提交请求
<p>username:
<input type="text" name="username"></p>
<p>target_name:
<input type="text">
<input type="text" name="target_name" value="kevin" style="display: none"> # 做处理(对接收转账人做隐藏处理 实际展示给用户的无作用)
</p>
<p>money:
<input type="text" name="money">
</p>
<p>
<input type="submit">
</p>
</form>
csrf操作
1.csrf操作:csrf语法会自动产生一个input里面会产生
2. 报错信息:Forbidden (403)
3. 操作方式
3.1 form表单操作:('django.middleware.csrf.CsrfViewMiddleware')全局校验查询通过csrf操作
<form action="" method="post">
{% csrf_token %} csrf语法(放在form表单中)
3.2 Ajax操作
方式一:通过csrf语法 在ajax语法中需要查询对应的值
{% csrf_token %}
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
data:{'name':'lili','csrfmiddlewaretoken':$("[name ='csrfmiddlewaretoken']").val()},
success(args) {
}
})
})
</script>
方式二:直接利用模板语法
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
data:{'csrfmiddlewaretoken':'{{ cref_token }}'},
success(args) {
}
})
})
</script>
方式三:通用方式(js脚本)
创建静态文件夹(static) 创建js文件(粘贴js代码 来源官方文档)
在html文件中引入该文件:<script src="/static/stati.js"></script
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);
}
}
});
装饰器
1. 因为中间件涉及全局校验 存在情况:
1.1 当整个网站默认都不校验csrf 但局部视图函数需要校验
1.2 当整个网站默认都校验csrf 但局部视图函数不需要校验
2.FBV操作校验相关装饰器
2.1 导入模块:在django.views.decorators.csrf中
csrf_protect:校验csrf
scrf_exempt:不校验csrf
2.2 根据不同情况将装饰器装到视图函数
2.3 代码操作:直接将装饰器安装至视图函数
@csrf_protect
@csrf_exempt
def func1(request):
return HttpResponse('123')
3.CBV操作校验相关装饰器:导入模块method_decorator(在django.utils.decorators中)
3.1 针对csrf_protect:校验csrf
方式一:装在请求函数上面 对某个函数起作用 @method_decorator(csrf_protect)
方式二:装在类上面 对类所有函数起作用 也可以运用name指明 @method_decorator(csrf_protect, name='post')
方式三:装在自己写的函数上面 对类中所有方法有用 @method_decorator(csrf_protect)
3.2 针对scrf_exempt:不校验csrf
方法一:装在自己写的函数上面 对类中所有方法有用 @method_decorator(csrf_exempt)
注:其余方法无效
3.3 代码操作:
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) 方式三
# @method_decorator(csrf_exempt) # 方法三 有效
def dispatch(self, request, *args, **kwargs):
return super(MyHome, self).dispatch(request, *args, **kwargs)
def get(self, request):
return HttpResponse('get方法')
# @method_decorator(csrf_protect) # 方法一
@method_decorator(csrf_exempt) # 方法一 无效
def post(self, request):
return HttpResponse('post方法')
auth模块
简介
django执行数据库迁移命令之后会产生一个auth_user表
该表可以配合auth模块做用户相关的功能:注册 登录 修改密码 注销 ...
该表还是django admin后台管理默认的表
django admin后台管理员账号创建
python manage.py createsuperuser
常见方法
先执行数据库迁移命令创建所需表(auth_user)
1.创建用户
from django.contrib.auth.models import User
User.object.create_user(username,password) # 创建普通用户
User.object.create_superuser(username,password,email) # 创建超级管理员用户
注:超级管理员创建可以通过命令行:createsuperuser 设置账户名及邮箱密码(可以在auth_user表中查看) 命令行只能创建超级管理员用户
2.校验用户名及密码是否正确
from django.contrib import auth
auth.authenticate(request, username=username, password=password)
3.用户登录
auth.login(request,user_obj)
4.判断用户是否登录
request.user.is_authecticated
5.获取登录用户对象
request.user
6.校验用户登录装饰器
from django.contrib.auth.decorators import login_required
跳转局部配置:login_required(login_url='/login/')
跳转全局配置:LOGIN_URL = '/login/'
7.校验密码是否正确
request.user.check_password(old_password)
8.修改密码
request.user.set_password(new_password)
request.user.save()
9.注销登录
auth.logout(request)
auth_user表切换
1.在models.py表中
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
phone = models.BigIntegerField() # 添加auth_user表中没有的字段
2.在配置文件settings.py中配置
AUTH_USER_MODEL = 'app01.UserInfo'
注:通过创建新的表 进行表的字段添加及表切换
基于中间件思想的插拔式设计
1.模块导入方法:
import....
from...import....
字符串方式导入
2.字符串方式导入模块
模块:import importlib
import.import_module(字符串)
底层原理:通过切割字符串从右切割1次 获取模块所在文件
3.方式
函数封装
配置文件插拔式设置