CBV添加装饰器 csrf跨站请求伪造 、装饰器 auth模块
CBV添加装饰器 csrf跨站请求伪造 、装饰器 auth模块
- CBV添加装饰器
- csrf跨站请求伪造
- csrf相关装饰器
- Auth模块
- 只要是跟注册,登录,修改密码,注销,验证是否登录等等
-
CBV添加装饰器
# 1. FBV: function based view 基于函数的视图函数 # 2. CBV:class based view 基于类的视图函数 1.from django.views import View #CBV必须继承View class IndexView(View): 2.导入模块 from django.utils.decorators import method_decorator 3.类添加装饰器 #类添加装饰器 #方拾2 针对不同方法添加不同的装饰器 @method_decorator(login_auth,name='get') #某个方法加装饰器 可以指定多个 @method_decorator(login_auth,name='post') #某个方法加装饰器 这样写的好处 这个方法可以装别的装饰器 class IndexView(View): # @method_decorator(login_auth) #某个方法饰器 方法1 #第三种方法 自定义dispatch方法 给这个装一个装饰器 会直接作用于当前类里所有的方法 def get(self,request): return HttpResponse('get方法再此') def post(self,request): return HttpResponse('post方法再此')
-
csrf跨站请求伪造
钓鱼网站 ''' 有一个正规的中国银行网站,我也写了一个跟中国银行网站一模一样的网站,用户不小心来到了我的网站,开始进行转账,前确实转到了中国银行系统,用户的钱也确实少了,但是,被转的用户不是用户想要转的账户 ''' 如何避免该问题? 在渲染form表单的时候,给一个随机的标识,下次提交的时候,后天验证该标识,如果不一样,说明不是我们的页面,直接403, 否则,验证通过 解决: 1. 加唯一标识 <form action="" method="post"> {% csrf_token %} # 生成唯一标识 </form> 2、ajax提交 $('.btn').click(function () { $.ajax({ url:'', type:'post', // ajax提交,随机字符串也应该提交过去 第一种方式 利用标签查找页面的随机字符串 data:{ 'username':'zhang', 'csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}, // 第二种方式 利用模板语法 data{ data:{ 'username':'zhang', 'csrfmiddlewaretoken': '{{ csrf_token }}'},#} } }) }) ################### 第三方方式 引入一个js文件通用方式 ############## #js静态文件如下 记得在settings配置一下 并引入这个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相关装饰器
''' 1. 全部都验证,但是就有几个方法不验证 2. 全部都不验证,但是,就有几个方法需要验证 ''' 先引入这两个装饰器 from django.views.decorators.csrf import csrf_exempt, csrf_protect 这两个装饰器分别是 csrf_protect: 需要验证 csrf_exempt:不需要验证 #FBV 里面 中间件 如果全部校验 某个函数想不校验可以加@csrf_exempt ,如果全部不校验 某几个想校验,那么可以加@csrf_protect CBV 符合之前的CBV装饰器的三种 #csrf_protect # @method_decorator(csrf_protect,name='post') #csrf_protect 第二种方式可以 class MyCsrfToken(View): @method_decorator(csrf_protect) # csrf_protect 第三种方式可以 def dispatch(self, request, *args, **kwargs): return super(MyCsrfToken, self).dispatch(request,*args,**kwargs) def get(self,request): return HttpResponse('get方法再此') #@method_decorator(csrf_protect) #csrf_protect 第一种方式可以 def post(self,request): return HttpResponse('post方法再此') ############## csrf_exempt######## # csrf_exempt 只有第三种方法可以 @method_decorator(csrf_exempt,name='post') #csrf_exempt 第二种方式不可以 class MyCsrfToken(View): @method_decorator(csrf_exempt) # csrf_protect 第三种方式可以 def dispatch(self, request, *args, **kwargs): return super(MyCsrfToken, self).dispatch(request,*args,**kwargs) def get(self,request): return HttpResponse('get方法再此') @method_decorator(csrf_exempt) #csrf_exempt 第一种方式不可以 def post(self,request): return HttpResponse('post方法再此')
-
Auth模块
''' 使用auth模块 就全部用auth模块 ''' # 创建django项目之后,执行数据库迁移命令,会生成一堆表,这些表里面有auth开头的,django开头的 django_session #存放的服务端session 用户相关数据 auth_user #存放的自带的admin页面 登录的管理员用户的账号密码 #登录该后台需要的用户名和密码参考的数据从auth_user表来,并且还要是超级管理员才能登录 # 1.创建超级管理员 python3 manage.py createsuperuser 会存在auth_user这个表里 密码是密文的 #创建普通用户 #2.登录 导入模块 from django.contrib import auth from django.contrib import auth def login(request): if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') #拿账号密码去数据库比对 # 表如何获取 # 密码如何比对 因为表里密码密文 获取的是明文 user_obj=auth.authenticate(request,username=username,password=password) # print(res) #符合返回数据对象 重写了__str__ 数据不符合返回None # print(res.username) #可以点 # print(res.password) ''' authenticate 实现了两件事 1.自动查找auth_user表 2.自动给密码加密比对 括号内必须同时传入用户名和密码 不能只传用户名 user_obj是一个数据对象 他自动写了一个__str__方法 为当前对象的username 如果不符合返回None ''' #判断用户名密码是否正确 if user_obj: #保存用户状态 让他一直是登录状态 操作session表 auth.login(request,user_obj) #等于 request.session['key']=user_obj #只要执行了上面这个方法 就可以在任何地方使用request.user拿到当前登录的对象 return redirect('/home/') return render(request,'login.html') #3.验证是否登录 #导入是否登录装饰器 from django.contrib.auth.decorators import login_required # login_url 未登录访问这个后面指定的地址 局部配置 还可以全局配置 全局配置后 就没必要加了 # @login_required (login_url='/login/') #该装饰器必须登录才可以访问下面方法 @login_required def home(request): # print(request.user) #拿到的用户对象 没登录拿到匿名用户AnonymousUser print(request.user.is_authenticated()) #判断用户是否登录 true登录 false未登录 return HttpResponse('home') ''' 全局配置和局部配置 都有的情况 局部配置大于全局配置 全局:不用重复写代码 ,跳转代码固定 局部:不同的视图函数在没有登录情况下可以跳转到不同页面 settings.py里面 #全局配置没有登录跳转到指定页面 LOGIN_URL='/login/' ''' # @login_required #(login_url='/login/') @login_required def index(request): return HttpResponse('index') #4.修改密码 @login_required def set_password(request): if request.method=='POST': old_password=request.POST.get('old_password') new_password=request.POST.get('new_password') confirm_password=request.POST.get('confirm_password') #校验老密码是否正确 if request.user.check_password(old_password): #校验新密码两次输入是否一致 if new_password==confirm_password: #写入新密码 不会影响数据库 修改对象的属性 request.user.set_password(new_password) request.user.save() #真正操作数据库 return render(request,'set_password.html',locals()) #5.注销 def loginout(request): auth.logout(request) #等于清空session和cookie request.session.flush() return redirect('/login/') #6.注册功能 from django.contrib.auth.models import User # User就是auth_user表 def register(request): if request.method=='POST': username = request.POST.get('username') password = request.POST.get('password') #操作user表 #创建普通用户create_user User.objects.create_user(username=username, password=password) #创建超级用户(了解) create_superuser email必须填 return render(request,'register.html',locals()) ##############总结方法############ 1. 登录功能 #比对用户名密码是否正确 user_obj = auth.authenticate(request, username=username, password=password) # 保存用户信息 auth.login(request, user_obj) # request.session['username'] = user_obj ''' 只要执行了auth.login(request,user_obj),那么,在全局任何地方都可以通过 request.user拿到用户对象, 封装到request.user ''' 2. 验证登录的装饰器 from django.contrib.auth.decorators import login_required 3. 验证是否登录 print(request.user.is_authenticated()) # 验证是否登录成功 4. 修改密码 # 1. 验证老密码是否正确 is_right = request.user.check_password(old_pwd) # 2. 真正的修改数据库 request.user.set_password(new_pwd) # 只是修改了属性,并没有操作数据库 request.user.save() # 这句话才真正操作数据库 5. 注销功能 auth.logout(request) # request.session.flush() 6. 注册功能 from django.contrib.auth.models import User # User就是auth_user表 User.objects.create_user(username=username, password=password) #创建超级用户(了解) create_superuser email必须填
扩展auth_user表字段
# 前提:如果你已经执行了数据库迁移命令,这个时候就不能在扩展auth_user表了 # 设计表阶段就要明确需不需要扩展表 from django.contrib.auth.models import User 1. 扩展auth_user表要继承AbstractUser类 auth_user表不会创建出来了 会出现一个新的表 你的类的名字就是表名 2. 扩展字段不要动原来的字段,你只需要在继承的类中写你自己想要扩展的字段 3. 生成一个新表,该表有原来的字段加上你扩展出来的字段 4. 在settings.py中加个配置: AUTH_USER_MODEL = '应用名.表名' 5. 扩展表之后,auth_user表就没有了