Django之中间件和Auth模块

CBV装饰器css

写一个装饰器在session上html

def login_auth(func):
  def inner(request,*args,**kwargs):
    if request.session.get('is_login'):
      return func(request,*args,**kwargs)
       else:
      return redirect('/login/')
    return inner

三种方法:jquery

第一种就是直接在里面给方法加上装饰器,方法上面加,不要用原生的装饰器,用的话,只能改参数,那样的话不通用ajax

第二种就是在类的上面加装饰器,name=‘方法’指向该方法数据库

from django.utils.decoration import method_decorator
#
@method_decorator(login_auth,name='get') # 第二种 name参数必须指定 class MyHome(View):
  # @method_decorator(login_auth) # 第一种 def get(self,request): return HttpResponse('get') def post(self,request): return HttpResponse('post')

第三种:利用dispatch来装饰全部的方法django

    class MyHome(View):
        @method_decorator(login_auth)  # 第三种  get和post都会被装饰
        def dispatch(self, request, *args, **kwargs):
            super().dispatch(request,*args,**kwargs)
        def get(self,request):
            return HttpResponse('get')

        def post(self,request):
            return HttpResponse('post')

 

中间件bootstrap

那么,咱们仍是先来看一下Django的请求生命周期后端

 

 

从上面的图中咱们能够发现,中间件在这其中起到了很重要的做用。浏览器

它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每一个中间件组件都负责作一些特定的功能。session

在settings文件里面就有这样的中间件配置

 


django默认有七个中间件,可是django暴露给用户能够自定义中间件而且里面能够写五种方法
ps:

1.请求来的时候会依次执行每个中间件里面的process_request方法(若是没有直接经过)
2.响应走的时候会依次执行每个中间件里面的process_response方法(若是没有直接经过)

django中间件可以帮我实现 网站全局的身份验证,黑名单,白名单,访问频率限制,反爬相关
》》》:django用来帮你全局相关的功能校验

自定义中间件
新建一个任意名字的文件夹,里面新建一个任意名字py文件

from django.utils.deprecation import MiddlewareMixin

插件类:

process_request:请求来的时候从上往下依次执行每个中间件里面的process_request


process_response :响应走的时候会从下往上依次执行每个中间件里面的process_response方法


process_view:路由匹配成功执行视图以前自动触发(从上往下依次执行)


process_exception:当视图函数报错了,自动触发(从下往上依次执行)


process_template_response:视图函数返回的对象有一个render()方法

(或者代表该对象是一个TemplateResponse对象或等价方法)(从下往上依次执行)

 

自定义中间件

from django.utils.deprecation import MiddlewareMixin


class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第一个自定义的中间件的process_request!')
# 写一个路由与视图,启动项目,查看打印结果。
# 再写一个自定义中间件

class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第二个自定义的中间件的process_request!')
# 诠释中间件的执行顺序


# 在两个中间件中添加process_response方法。研究中间件消息进出的顺序
class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第一个自定义的中间件的process_request!')
    def process_response(self,request,response):
          print('我是第一个自定义的中间件的process_response')
        return response
# 再来研究process_request中直接返回HttpReponse对象,会怎么走接下来的process_response

# process_view,process_exception,process_template_response

 

csrf(跨站请求伪造)

先写一个简单的post请求,复现报错信息

钓鱼网站:银行转帐的路径,你是否也能够拿到,而后你作一个跟银行如出一辙的页面,也超银行的借口提交数据,当用户在钓鱼网站输入对方帐户名和转帐金额以后,点击发送。其实内部是将对方帐户换成了钓鱼网站的造假人员的帐户。形成你转帐转错帐户的状况

开两个django项目,模拟转帐的现象

如何区分钓鱼网站和正经网站?在正经网站返回页面的时候,在form表单中偷偷塞一个特殊的字符串,后端记下该页面对应的字符串的值,等用户发post请求来的时候,我先去校验特殊的字符串是否匹配

如何去写这个特殊的字符串呢?模版语法有一个固定的写法{% csrf_token %},必须写在form表单内

浏览器查看改标签的值,而且每次都在刷新。再来演示刚刚转帐的示例

ajax中如何设置csrf_token

 

# 只想给某个视图韩式加上csrf校验
from django.views.decorators.csrf import csrf_exempt,csrf_protect

# 局部禁用
@csrf_exempt
def index(request):
  pass

# 局部使用
@csrf_protect
def login(request):
  pass

 

转帐钓鱼案例

def transfer(request):
    if request.method == 'POST':
        username = request.POST.get("username")
        money = request.POST.get('money')
        others = request.POST.get('others')
        print('%s 给 %s 转了 %s'%(username,others,money))
    return render(request,'transfer.html')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<h1>正经的网站</h1>
<form action="/index3/" method="post">
{#    {% csrf_token %}#}
    <p>username:<input type="text" name="username"></p>
    <p>money:<input type="text" name="money"></p>
    <p>others:<input type="text" name="others"></p>
    <input type="submit">
</form>
<button>ajax</button>
<script>
    $('button').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'name':'khan','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
            success:function (data) {
                console.log(data)
            }
        })
    })

</script>

</body>
</html>

另起一个项目,钓鱼页面与原始页面相似

经过像原网站发送请求,钓鱼网站的一个input框就用户替换了,这时候钱天然就流向了非法分子,有了{% csrf_token %},那么服务端就不在接受钓鱼网站的post请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<h1>钓鱼网站</h1>
<form action="http://127.0.0.1:8000/transfer/" method="post">
    <p>username:<input type="text" name="username"></p>
    <p>money:<input type="text" name="money"></p>
    <p>others:<input type="text"></p>
    <input type="text" name="others" value="khan" style="display:none">
    <input type="submit">
</form>
</body>
</html>

 

Auth认证模块

 执行数据库迁移的那两条命令时,即便咱们没有建表,也会出现autho_user表,咱们一块儿来看一下怎么操做该表。

from django.contrib import auth
from django.contrib.auth.models import User
def auth_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # models.User.objects.filter(username=username,password=password).first()
        user_obj = auth.authenticate(request,username=username,password=password)
        if user_obj:
            # 记录用户状态
            # request.session['name'] = 'khan'
            auth.login(request,user_obj)  # 一旦记录了,能够在任意的地方经过request.user获取到当前登陆对象
            return HttpResponse('ok')

    return render(request,'auth_login.html')


def auth_index(request):
    print(request.user.is_authenticated())  # 判断当前用户是否已经登陆
    print(request.user,type(request.user))  # 获取当前登陆用户对象
    return HttpResponse('ok')


def auth_logout(request):
    auth.logout(request)  # request.session.flush()
    return HttpResponse('ok')


def auth_register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = auth.authenticate(request,username=username)
        if user_obj:
            return HttpResponse('当前用户已存在')
        # models.User.objects.create(username=username,password=password)
        # User.objects.create(username=username,password=password)  # 不能再用create建立
        # User.objects.create_user(username=username,password=password)  # 建立普通用户
        User.objects.create_superuser(username=username,password=password,email='123@163.com')  # 建立超级用户
    return render(request,'auth_register.html')

def auth_password(request):
    print(request.user.password)
    is_res = request.user.check_password('khan123')  # 校验密码是否一致
    if is_res:
        request.user.set_password('666')  # 设置新密码
        request.user.save()  # 修改密码必须save保存  否则无效
    return HttpResponse('ok')

装饰器校验是否登录及跳转

from django.contrib.auth.decorators import login_required

@login_required(login_url='/login/',redirect_field_name='old') 
# 没登录会跳转到login页面,而且后面会拼接上你上一次想访问的页面路径/login/?next=/test/,能够经过参数修改next键名 def my_view(request): pass

若是我全部的视图函数都须要装饰并跳转到login页面,那么我须要写好多份。

其实能够去settings里面去配置

# 能够在配置文件中指定auth校验登录不合法统一跳转到某个路径
LOGIN_URL = '/login/'  # 既能够局部配置,也能够全局配置

 

自定义模型表应用auth功能

第一种:能够创建一对一关系的模型表

from django.contrib.auth.model import User

class UserDetail(models.Models):
  phone = models.CharField(max_length=11)
  user = models.OnoToOneField(to=User)

第二种:面向对象继承

from django.contrib.auth.models import User,AbstractUser
class UserInfo(AbstractUser):
  phone = models.CharField(max_length=32)

# 须要在配置文件中,指定我再也不使用默认的auth_user表而是使用我本身建立的Userinfo表
AUTH_USER_MODEL = "app名.models里面对应的模型表名"
相关文章
相关标签/搜索