zoukankan      html  css  js  c++  java
  • Django中间件进行用户登陆验证

    通常情况下我们在django中设置登陆验证,使用装饰器来检验是否登陆过。这种情况,我们所有的视图函数都需要加上,太low。

    下面我们使用中间件来进行登陆验证~~~

    我们先做出登陆页面:

    1、models.py

    #先在models中设置用户名密码字段
    from django.db import models
    
    class UserInfo(models.Model):
        # nid = models.AutoField(primary_key=True)
        # nid = models.BigAutoField(primary_key=True)
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)

    2、新建forms.py

    from django.forms import Form
    from django.forms import fields
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    class LoginForm(Form): username = fields.CharField( label='用户名',#模板中使用form.username.label required=True, error_messages={ 'required':'用户名不能为空' }, widget=widgets.TextInput(attrs={'class':'form-control'}) ) password = fields.CharField( label='密码', required=True, error_messages={ 'required': '密码不能为空' }, widget=widgets.PasswordInput(attrs={'class':'form-control'}) )
    #form钩子
        def clean_username(self):
    if not self.cleaned_data.get("username").isdigit():
    return self.cleaned_data.get("username")
    else:
    raise ValidationError("用户名不能全是数字")
     

    3、views.py

    
    
    # ############## 自定义配置 #################
    USER_SESSION_KEY = "user_info"
    from django.conf import settings# 仅用户自定义+内置
    # from s18day24 import settings # 仅用户自定义

    def
    login(request): #第一次请求走GET,显示初始登陆页 if request.method == "GET": form = LoginForm() return render(request,'login.html',{'form':form}) #如果是post请求,说明用户在登陆 else: #这里我们将request.POST字典完整的抛给form进行form校验 form = LoginForm(request.POST) #如果form校验成功 if form.is_valid(): # form.cleaned_data # {'username':'alex','password':'xxxx'} # 数据库中查出是否存在用户名密码对应记录models.UserInfo.objects.filter(username=form.cleaned_data['user'],password=form.cleaned_data['pwd']) # models.UserInfo.objects.filter(**{'username':'alex','password':123}) form.cleaned_data['password'] = md5(form.cleaned_data['password']) user = models.UserInfo.objects.filter(**form.cleaned_data).first() if user: # 将用户信息放置到session中,user.pk是UserInfo表的主键 request.session[settings.USER_SESSION_KEY] = {'id':user.pk,'username':user.username } return redirect('/index/') else:
    #给errors_message字典添加错误信息 form.add_error(
    'password', '用户名或密码错误') return render(request, 'login.html',{'form':form})
    @auth#添加装饰器后使用
    def index(request):
    return HttpResponse('欢迎登陆')

    4、login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        #novalidate不适用浏览器自带验证功能
        <form method="post" novalidate>
            {% csrf_token %}
            #form提供的label属性errors错误字典,form生成html
            <p>{{ form.username.label }}: {{ form.username }} {{ form.username.errors.0 }}</p>
            <p>{{ form.password.label }}: {{ form.password }} {{ form.password.errors.0 }}</p>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    md5加密模块

    import hashlib
    
    def md5(text):
        m = hashlib.md5()
        m.update(text.encode('utf-8'))
        return m.hexdigest()

    5、urls.py模块

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
    
        # url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login),
        url(r'^index/', views.index),
        url(r'^test/', views.test),
    ]

    这种情况下,我们是可以轻松直接访问index页面的

    我们想让用户在未登录的情况下不允许访问index,需要添加个装饰器来进行校验是否登陆,方法如下。

    def auth(func):
        def inner(request,*args,**kwargs):
            # 在登陆时,我们给登陆成功的用户设置了session,在执行视图函数之前,我们获取用户访问session看能否找到
            user_info = request.session.get(settings.USER_SESSION_KEY)
            if not user_info:
                return redirect('/login/')
            # 执行视图函数
            response = func(request,*args,**kwargs)
            return response
        return inner

    dango的生命周期

    我们抛开装饰器用户,我们先来说下django一条请求的生命周期

    一条请求进入dango我们通常用到的,请求进入我们设置id路由系统,进行url匹配视图函数,在视图函数中进行一些验证、数据库操作、渲染html等操作。

    在我们进入url试图函数之前,请求实际还会经过几个中间件,其实就是几个定义的类,我们知道的 csrf校验就是从这里面进行的。

    我们可以这样找到这些类

    在setting中middleware中定义的就是一个个中间件

     我们使用from。。。import的方法ctrl点击找到这个类

     

    我们在项目中新建个middlwares文件

    创建个py文件md.py,定义两个类,m1、m2

    setting中配置上路径

    在django1.7或1.8的时候

    我们在自定义的中间件中那么定义

    class M1(object):
        def process_request(self,request,*args,**kwargs):
            pass
        def process_response(self,request,response):
            return response
    class M2(object):
        def process_request(self,request,*args,**kwargs):
            pass
        def process_response(self,request,response):
            return response

    1.10之后,中间件默认会先执行__call__方法

    class MiddlewareMixin(object):
        def __init__(self, get_response=None):
            self.get_response = get_response
            super(MiddlewareMixin, self).__init__()
    
        def __call__(self, request):
            response = None
            if hasattr(self, 'process_request'):
                response = self.process_request(request)
            if not response:
                response = self.get_response(request)
            if hasattr(self, 'process_response'):
                response = self.process_response(request, response)
            return response

    执行顺序为 m1.process_request-->m2.process_request-->m2.process_response-->m1.process_response

    注:其中retrun  response 的作用是为了传递前面函数的返回内容

    from django.conf import settings
    from django.shortcuts import redirect
    class MiddlewareMixin(object):
        def __init__(self, get_response=None):
            self.get_response = get_response
            super(MiddlewareMixin, self).__init__()
    
        def __call__(self, request):
            response = None
            if hasattr(self, 'process_request'):
                response = self.process_request(request)
            if not response:
                response = self.get_response(request)
            if hasattr(self, 'process_response'):
                response = self.process_response(request, response)
            return response
    
    class M1(MiddlewareMixin):
        def process_request(self,request,*args,**kwargs):
            #如果是登陆页面,returnNone跳过
            if request.path_info=='/login/':
                return None
            #如果是其他url,进行校验是否登陆
            user_info=request.session.get(settings.USER_SESSION_KEY)
            if not user_info:
                return redirect('/login/')
        def process_response(self,request,response):
            #用于传递给前面的类
            print("m1.process_response")
            return response

    如上,我们将session验证登陆放到中间件中,便可以替代装饰器了~

    中间件中定义的方法是固定的,常用的是process_request和process_response,还有一些其他的方法:

    process_view(self,request,callback,callback_args,callback_kwargs): 当执行完process_request之后,会重新回到入口执行process_view然后执行url函数。

    process_exception(request,exception):如果项目中模块中出现异常,返回时会先执行中间件的process_exception,之后回到返回点执行process_response。

    总结:

        1、settings 中middleware中添加自定义中间件路径

    'middlwares.auth.M1',

    2、新建middlwares文件夹auth文件
    3、1.10版本以上自定义中间件类需要继承MiddlewareMixin
    4、须有 process_request ,和process_response方法,process_response的需要返回return response,process_request 默认return None相当于跳过该中间件。
    
    
  • 相关阅读:
    zookeeper项目使用几点小结
    Dubbo架构设计详解
    关于web.xml不同版本之间的区别
    bat定时执行,清除PHP缓存
    新闻列表标题省略样式
    php把时间格式化
    HTML5中的拖放
    Redis JAVA客户端 Jedis常用方法
    Redis 简介
    SpringBoot DataSource 配置说明
  • 原文地址:https://www.cnblogs.com/kunixiwa/p/8157296.html
Copyright © 2011-2022 走看看