day61
跨站请求伪造csrf
钓鱼网站
你自己写一个跟中国银行正规网站一模一样的页面
用户输入用户名 密码 对方账户 转账金额提交
请求确实是朝中国银行的接口发送的 钱也扣了
但是对方账户变了 变成了钓鱼网站自己提前设置好的账户
如何实现
你在写form表单的时候 让用户填写的对方账户input并没有name属性
而是你自己在内部偷偷隐藏了一个具有name属性的input框
并且value值是你自己的账户 然后将该标签隐藏了
模拟该现象的产生
创建两个django项目
如何解决该问题
只处理本网站发送的post请求
如何识别如何判断当前请求是否是本网张发出的
解决
网站在返回给用户一个form表单的时候 会自动在该表单隐藏一个input框
这个框的value是一个随机字符串 但是网站能够记住每一个浏览器发送的随机字符串
form表单解决
以后在写form表单的时候 你只需要在表单中写一个{% csrf_token %}
<form action="" method="post">
{% csrf_token %}
<p>username:<input type="text" name="username"></p>
<p>target_account:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form>
<input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">
ajax如何解决
方式1 较为繁琐
先在页面任意的位置上书写{% csrf_token %}
然后在发送ajax请求的时候 通过标签查找获取随机字符串添加到data自定义对象即可
data:{'username':'jason','csrfmiddlewaretoken'😒('input[name="csrfmiddlewaretoken"]').val()},
方式2 较为简单
data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
方式3 官网提供的文件 最通用的一种方式(全能)
直接兴建js文件拷贝代码 导入即可
你不需要做任何的csrf相关的代码书写
csrf相关的装饰器
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt # 不校验 csrf
def index(request):
return HttpResponse('index')
@csrf_protect # 校验
def login(request):
return HttpResponse('login')
这两个装饰器在CBV上有何异同:
@method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
@method_decorator(csrf_exempt,name='dispatch') # csrf_exempt
class MyIndex(views.View):
@method_decorator(csrf_exempt) # 可以
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
@method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
def post(self,request):
return HttpResponse('OK')
csrf_exempt这个装饰器只能给dispatch装才能生效
"""
csrf_protect方式全都可以 跟你普通的装饰器装饰CBV一致
"""
@method_decorator(csrf_protect,name='post') # 可以
class MyIndex(views.View):
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
@method_decorator(csrf_protect) # 可以
def post(self,request):
return HttpResponse('OK')
django settings源码剖析
django有两个配置文件
一个是暴露给用户可以配置的
一个是内部全局的(用户配置了就用用户的 用户没有配就用自己的)
obj
obj.name = 'egon' # 全局
obj.name = 'jason' # 局部
先加载全局配置 给对象设置
然后在加载局部配置 再给对象设置
一旦有重复的项 后者覆盖前者
auth模块
auth模块常用方法
如何创建超级用户(root)
python3 manage.py createsuperuser
创建用户:
from django.contrib.auth.models import User
User.objects.create(username=username,password=password)
不可用 密码不是加密的
User.objects.create_user(username=username,password=password)
创建普通用户 密码自动加
User.objects.create_superuser(username=username,password=password,email='123@qq.com')
创建超级用户 需要邮箱数据
校验用户名和密码是否正确:
from django.contrib import auth
user_obj = auth.authenticate(request,username=username,password=password)
必须传用户名和密码两个参数缺一不能
保存用户登录状态
auth.login(request,user_obj)
只要这句话执行了 后面在任意位置 只要你能拿到request你就可以通过request.user获取到当前登录的用户对象
判断当前用户是否登录
request.user.is_authenticated()
校验原密码是否正确
request.user.check_password(old_password)
修改密码
request.user.set_password(new_password)
request.user.save() # 千万不要忘了
注销
auth_logout(request)
校验用户是否登录装饰器
from django.contrib.auth.decorators import login_required
局部配置
@login_required(login_url='/login/')
def index(request):
pass
全局配置
settings配置文件中 直接配置
LOGIN_URL = '/login/'
@login_required
def index(request):
pass
如果全局配置了 局部也配置 以局部的为准
如何扩展auth_user表字段
方式1
利用一对一外键字段关系
class UserDetail(models.Model):
phone = models.BigIntegerField()
user = models.OneToOneField(to='User')
方式2
利用继承关系
from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
phone = models.BigIntegerField()
register_time = models.DateField(auto_now_add=True)
一定要注意 还需要去配置文件中配置
AUTH_USER_MODEL = 'app01.Userinfo' # 应用名.表名
这么写完之后 之前所有的auth模块功能全都以你写的表为准