django学习笔记
今日内容概要
- csrf跨站请求伪造
- csrf相关装饰器
- auth认证模块
- 基于django中间件设计项目功能
今日内容详细
csrf跨站请求伪造
简介
钓鱼网站:一个模仿正规网站的网址 诱骗用户在该网站上做本应该在正规网站上做的操作,从而获取到该用户在正规网站上的数据甚至是财产。eg:假设我们需要登录网页完成转账操作,我们不小心登录到了钓鱼网站,是一个跟银行一摸一样的网址页面,用户再该页面上转账账户的钱会减少,但是受益人却不是自己想要转账的那个人。
模拟钓鱼网站:
一台计算机上两个服务端不同端口启动,钓鱼网站提交地址改为正规网站地址。
原理:将收款人的账号,提前写成诈骗分子的然后隐藏,暴露给用户一个没有name属性的标签写着玩。
<p>当前账户:<input type="text" name="username"></p>
<p>目标账户:<input type="text" ></p> # 写着玩,没有功能
<p>目标账户:<input type="text" name="target_user" style="display: none" value="诈骗分子"></p> # 真正转账对象,通过display: none隐藏了
<p>转账金额:<input type="text" name="money"></p>
如何预防钓鱼网站:
csrf策略:通过在返回的页面上添加独一无二的标识信息从而区分正规网站和钓鱼网站的请求。
csrf操作
form表单:
<form action="" method="post">
{% csrf_token %}
<p>当前账户:<input type="text" name="username"></p>
<p>目标账户:<input type="text" name="target_user"></p>
<p>转账金额:<input type="text" name="money"></p>
<input type="submit">
</form>
会自动产生一个input标签,用于校验。submit提交的时候会带上这个生成的input里的value值,然后会和之前后端返回的页面里的value进行比对,如果正确,这个提交请求就让它过,如果不正确就不让请求通过。
<input type="hidden" name="csrfmiddlewaretoken" value="iQOCyIe4ETIYSfVSji3SqJlt3XeEJs8pujSuiNG5aKHrKZbfzusiLQ5erZHnfpk8"> # value随机
ajax:
方式1:先编写csrf模板语法,然后利用标签查找和值获取,手动添加
'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()
方式2:直接利用模板语法即可
'csrfmiddlewaretoken':'{{ csrf_token }}'
方式3:通用方式(js脚本)扩展性最高
js脚本自动处理(只能适用于ajax提交),创建一个js文件,复制下面内容,然后在页面上引入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);
}
}
});
csrf相关装饰器
当整个网站默认都不校验csrf,但是局部视图函数需要校验,如何处理
csrf_protect 校验csrf
当整个网站默认都校验csrf,但是局部视图函数不需要校验,如何处理
csrf_exempt 不校验csrf
针对FBV
from django.views.decorators.csrf import csrf_protect,csrf_exempt
# @csrf_protect
@csrf_exempt
def home(request):
return HttpResponse('哈哈哈')
针对CBV
针对CBV不能直接在方法上添加装饰器 需要借助于专门添加装饰器的方法
csrf_protect:三种CBV添加装饰器的方式都可以
csrf_exempt:只有方式3可以生效(给重写的dispatch方法装)
# @method_decorator(csrf_protect,name='post') # 可以 # 方式2:指名道姓的添加
# @method_decorator(csrf_exempt,name='post') # 无效
class MyView(views.View):
# @method_decorator(csrf_protect) # 可以 # 方式3:影响类中所有的方法
@method_decorator(csrf_exempt) # 有效
def dispatch(self, request, *args, **kwargs):
return super(MyView, self).dispatch(request,*args,**kwargs)
# @method_decorator(csrf_protect) # 可以
# @method_decorator(csrf_exempt) # 无效
def post(self,request): # 方式1:指名道姓的添加
return HttpResponse('Home Post view')
auth认证模块
简介
django执行数据库迁移命令后会产生一个auth_user表,该表可以配合auth模块做用户相关的功能,eg:注册、登录、修改密码、注销...。该表还是django admin后台管理默认的表
django自带的admin后台管理用户登录参考的就是auth_user表。
创建admin后台管理员用户
python manage.py createsuperuser
自动对用户密码进行加密处理并保存
auth模块常见功能
1.创建用户
from django.contrib.auth.models import User
User.object.create_user(username,password) # 普通用户
User.object.create_superuser(username,password,email) # 管理员
2.校验用户名和密码是否正确
from django.contrib import auth
auth.authenticate(request,username,password) # 校验正确返回的是用户对象 错误返回的是None
3.用户登录
auth.login(request,user_obj) # 自动帮你操作cookie与session相关
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_passowrd) # 临时修改密码
request.user.save() # 将修改操作同步到数据库中
9.注销登录
auth.logout(request) # 自动清除cookie和session
auth_user表切换
我们想使用auth模块的方法并且还想扩展auth_user表字段
方式1:编写一对一表关系(了解)
方式2:类继承(推荐)
# models.py
from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
'''扩展auth_user表中没有的字段 不能冲突'''
phone = models.BigIntegerField()
desc = models.TextField()
# settings.py
'''告诉auth模块 不再使用auth_user 而是使用自定义的表'''
AUTH_USER_MODEL = 'app01.Userinfo'
注意:
- 类继承之后,需要重新执行数据库迁移命令,并且库里面是第一次操作才可以
- auth模块所有的方法都可以直接在自定义模型类上面使用,自动切换参照表
基于django中间件设计项目功能
importlib模块:可以通过字符串的形式导入模块
常规导入方式
方式1:import 句式
方式2:from ... import ... 句式
from bbb import b
from bbb.b import name # 可以直接导变量数据
print(b) # <module 'bbb.b' from '/Users/jiboyuan/PycharmProjects/day64_1/bbb/b.py'>
print(b.name)
字符串导入方式
import importlib
module_path = 'bbb.b'
res = importlib.import_module(module_path)
print(res.name)
module_path1 = 'bbb.b.name'
importlib.import_module(module_path1) # 不可以 最小导入单位是模块文件级别
以发送提示信息为需求编写功能的案例
方式1:简单的函数式封装
方式2:配置文件插拔式设计:
# settings
NOTIFY_FUNC_LIST = [
'notify.qq.QQ',
'notify.email.Email',
'notify.msg.Msg',
'notify.weixin.WeiXin',
]
# __init__
import settings
import importlib
def send_all(msg):
# 1.循环获取配置文件中字符串信息
for str_path in settings.NOTIFY_FUNC_LIST: # 'notify.qq.QQ'
# 2.切割路径信息
module_path, class_str_name = str_path.rsplit('.', maxsplit=1) # ['notify.qq','QQ']
# 3.根据module_path导入模块文件
module = importlib.import_module(module_path) # from day64.notify import qq
# 4.利用反射获取模块文件中对应的类名
class_name = getattr(module, class_str_name) # Email Msg QQ
# 5.实例化
obj = class_name()
# 6.调用发送消息的功能
obj.send(content)
链式调用:
写一个类,类中的方法,每次都返回对象本身
class Person:
def change_name(self,name):
self.name=name
return self
def change_age(self,age):
self.age=age
return self
person.change_name(lqz)
person.change_age(19)
person.change_name(lqz).change_age(19)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库