day61

£可爱£侵袭症+ 提交于 2019-12-06 15:12:54

跨站请求伪造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模块功能全都以你写的表为准

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!