CSIC_716_20200114【Django入门---django中间件、csrf跨站请求伪造、auth认证】

中间件

凡是全局相关的功能,都可以考虑使用中间件来实现。例如:全局的身份校验、访问频率校验、访问黑名单、访问白名单。

中间件总共有5个方法可以使用:

process_request

请求从web服务网关接口传到中间件层时,会按照先后顺序依次执行每一个中间件里的process_request方法,遇到没有process_request的中间件会直接跳到下一个中间件。如果不满足其中任何一个就会被拒绝访问。如果process_request返回了一个值HttpResponse对象,那么程序就会从此原路返回,返回的路线要么经过process_response,如果没有process_response也能直接通过HttpResponse返回到前端。

process_response

当执行完视图函数后,程序会按照与process_request相反的顺序执行process_response方法。
该方法必须要有return返回值,否则报错。一般是return response,也可以自己返回一个HttpResponse替换从视图函数传过来的值,外层可以偷换内层传出来的东西

process_view

在中间件放行后,执行视图函数之前,会执行process_view

process_template_response

他在视图函数执行完之后,process_response执行前执行,他的执行顺序和process_response一样,顺序反向。他触发的条件是:视图函数返回的对象中必须要有render属性对应的render方法。

process_exception

在视图函数报错的时候触发,顺序也是反向的。

上面五个方法的执行顺序:

 

 csrf

form表单如何通过csrf校验
你只需要在你的form表单内写一个
{% csrf_token %}


ajax如何通过csrf校验

// 第一种方式 自己手动获取
{#data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
// 第二种方式 利用模板语法
{#data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
// 第三种 通用方式 引入外部js文件 官网提供的方式
{% load static %}
<script src="{% static 'myset.js' %}"></script>
data:{'username':'jason'}

 其中导入Ajax跨站请求伪造的js文件为

 1 function getCookie(name) {
 2     var cookieValue = null;
 3     if (document.cookie && document.cookie !== '') {
 4         var cookies = document.cookie.split(';');
 5         for (var i = 0; i < cookies.length; i++) {
 6             var cookie = jQuery.trim(cookies[i]);
 7             // Does this cookie string begin with the name we want?
 8             if (cookie.substring(0, name.length + 1) === (name + '=')) {
 9                 cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
10                 break;
11             }
12         }
13     }
14     return cookieValue;
15 }
16 var csrftoken = getCookie('csrftoken');
17 function csrfSafeMethod(method) {
18   // these HTTP methods do not require CSRF protection
19   return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
20 }
21 
22 $.ajaxSetup({
23   beforeSend: function (xhr, settings) {
24     if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
25       xhr.setRequestHeader("X-CSRFToken", csrftoken);
26     }
27   }
28 });
导入Ajax的跨站请求代码

 


			
	csrf相关装饰器
		当我们网站整体都校验csrf的时候 我想让某几个视图函数不校验
		
		当我们网站整体都不校验csrf的时候 我想让某几个视图函数校验
		

		from django.views.decorators.csrf import csrf_exempt, csrf_protect
		from django.views import View9
		from django.utils.decorators import method_decorator

		# @method_decorator(csrf_protect,name='post')  # 第二种指名道姓的给类中某个方法装
		# @method_decorator(csrf_exempt,name='post')  # csrf_exempt 第二种方式不行
		@method_decorator(csrf_exempt,name='dispatch')  # 可以!!!
		class MyHome(View):  # APIView
			# @method_decorator(csrf_protect)  # 第三种 类中所有的方法都装
			# @method_decorator(csrf_exempt)  # csrf_exempt 第三种方式可以
			def dispatch(self, request, *args, **kwargs):
				return super().dispatch(request,*args,**kwargs)

			def get(self,request):
				return HttpResponse('get')
			# @method_decorator(csrf_protect)  # 第一种方式
			# @method_decorator(csrf_exempt)  # csrf_exempt 第一种方式不行
			def post(self,request):
				return HttpResponse('post')

  

"""
给CBV加装饰器 推荐你使用模块method_decorator
我们自己写的装饰器和csrf_protect用法一致
唯独csrf_exempt是一个特例 只能给dispatch方法装
"""

auth模块
django用户相关的自带的功能模块 auth_user表


如何创建超级用户
createsuperuser

模块导入
from django.contrib import auth
from django.contrib.auth.models import User


auth方法大全

1.创建用户
User.objects.create() # 密码是明文
User.objects.createuser() # 基本都用它 
User.objects.createsuperuser() # 邮箱要给数据

2.校验用户名和密码是否正确
auth.authenticate(username=username,password=password) # 用户名和密码两个一个都不能少
# 该方法当用户名和密码正确的时候返回的用户对象 不正确返回None

3.保存用户登录状态
auth.login(request,user_obj) # 这一句执行之后 request.user获取当前登录的用户对象

4.如何判断当前用户是否登录 以及如何获取当前登录用户对象
request.user.is_authenticated() # 判断是否登录
request.user # 登录用户对象

5.校验用户是否登录
from django.contrib.auth.decorators import login_required
# 局部配置
@login_required(login_url='/login/')
def xxx(request):
return HttpResponse('xxx页面')

# 全局配置
配置文件中写以下代码
LOGIN_URL = '/login/'
@login_required
def xxx(request):
return HttpResponse('xxx页面')

# 如果两个都设置了 那么优先执行局部配置

6.修改密码
request.user.check_password(old_password) # 校验原密码是否正确

request.user.set_password(new_password)
request.user.save() # 一定要保存 

7.注销功能
auth.logout(request)

  

from django.contrib import auth
from django.contrib.auth.models import User
def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 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')  # 不能使用 密码变成明文的了
    return render(request,'register.html')


def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')  # 明文
        # 数据库校验用户名和密码是否正确
        # User.objects.filter(username=username,password=password)
        user_obj = auth.authenticate(request,username=username,password=password)
        """
        用户名密码正确返回的是用户对象
        错误返回None
        """
        # print(res)
        # print(res.username)
        # print(res.password)
        if user_obj:
            # 保存用户登录状态
            # request.session
            auth.login(request,user_obj)
            """
            只要执行了这一句话 之后在任意可以获取到request对象的地方
            都可以通过request.user获取到当前登录的用户对象
            """
            return HttpResponse("登录成功")
    return render(request,'login.html')


def get_user(request):
    print(request.user)
    """
    用户登录成功之后 request.user拿到的就是用户对象
    没有登录 获取到的匿名用户
    """
    print(request.user.is_authenticated())
    return HttpResponse("get_user")

# 校验用户是否登录装饰器
from django.contrib.auth.decorators import login_required


# @login_required(login_url='/login/')
@login_required
def xxx(request):
    return HttpResponse('xxx页面')

# @login_required(login_url='/login/')
# @login_required
@login_required(login_url='/jskahdhsajhdjsadhjk/')
def yyy(request):
    return HttpResponse('yyy页面')

# @login_required(login_url='/login/')
@login_required
def zzz(request):
    return HttpResponse('zzz页面')


@login_required
def set_password(request):
    if request.method == 'POST':
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        # 1 先校验旧密码是否正确
        is_right = request.user.check_password(old_password)
        # print(is_right)
        # 2 再去修改新密码
        if is_right:
            request.user.set_password(new_password)
            request.user.save()  # 一定要save一下  否则无影响
    return render(request,'set_password.html')


@login_required
def logout(request):
    auth.logout(request)
    return HttpResponse('注销成功')
View Code



如何扩展auth_user表
# 1 利用一对一表关系()

# 2 利用类的继承
# 1 类的继承

from django.contrib.auth.models import User,AbstractUser
# Create your models here.
class Userinfo(AbstractUser):
phone = models.BigIntegerField()
avatar = models.FileField()
# 扩展的字段 尽量不要与原先表中的字段冲突

  



# 2 配置文件
AUTH_USER_MODEL = '应用名.表名'
"""
django就会将userinfo表来替换auth_user表
并且之前auth模块所有的功能不变 参照的也是userinfo表
"""

原文地址:https://www.cnblogs.com/csic716/p/12194242.html