zoukankan      html  css  js  c++  java
  • Django之session验证的三种姿势

    一.什么是session

    session是保存在服务端的键值对,Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。

    二.FVB中使用装饰器进行session验证

    认证装饰器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 登陆验证
    def auth(func):
     '''判断是否登录装饰器'''
        def inner(request, *args, **kwargs):
            ck = request.session.get("username")
            '''如果没有登陆返回到login.html'''
            if not ck:
                return redirect("/login.html")
            return func(request, *args, **kwargs)
        return inner

     在需要认证的函数执行前加上装饰器认证即可,实际中应用如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    def login(request):
        if request.method == "GET":
            return render(request, "login.html")
        else:
            username = request.POST.get("user")
            pwd = request.POST.get("pwd")
            pwd = md5(pwd)
            dic = {"flag":False}
            obj = User.objects.filter(username=username, pwd=pwd).first()
            if obj:
                request.session["username"= username
                return redirect("/index.html")
            else:
                print(dic)
                return HttpResponse(json.dumps(dic))
     
    @auth
    def index(request):
        user = request.session.get("username")
        business = Business.objects.all().values("name")
        host_list = Host.objects.all().values("id","host","port","business__name")
        username = User.objects.all().values("username")
        return render(request, 'index.html', {'host_list':host_list,"business":business,"user":user,"username":username})
         
    @auth
    def addhost(request):
        business = Business.objects.all().values("name")
        if request.method == "POST":
            user = request.session.get("username")
            host = request.POST.get("host")
            port = request.POST.get("port")
            select_business = request.POST.get("business")
            business_id = Business.objects.filter(name=select_business).values("id")[0]
            host = Host.objects.create(host=host,
                                      port=port,
                                      business_id=business_id["id"])
            # host.business.add(*business)
            return render(request, "index.html")
     
        return render(request, "index.html", {"business":business})
         
    @auth
    def up_business(request):
        if request.method == "POST":
            user = request.session.get("username")
            host= request.POST.get("host")
            port= request.POST.get("port")
            business_name = request.POST.get("business")
            username = request.POST.get("username")
            print(host,port,business_name,username)
            return render(request,"保存成功")

     三.CBV中使用类继承的方式进行session认证

    • cbv是 class based view(基于类)
    • cbv基于dispatch进行反射,get获取,post提交
    • 应用场景:登录认证(继承dispatch,在dispatch里做session验证)

    CBV第一种方式继承

    1.单继承

    扫盲:(继承的时候,一定要清楚self是哪个类实例化出来的对象,下例,self为B实例化的对象,任何属性优先从自己里面找,找不到在去父类里找)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class A(object):
        def aaa(self):
            print('from A')
        def bbb(self):
            self.aaa()
      
    class B(A):
        def aaa(self):
            print('from B')
      
    = B()
    c.aaa()

    应用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from django.views import View
    class BaseView(View):
        def dispatch(self, request, *args, **kwargs):  # 继承父类的dispatch,因为父类里有返回值,所以也要有return
            if request.session.get('username'):
                response = super(BaseView, self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')
      
    class IndexView(BaseView):
      
        def get(self, request, *args, **kwargs):
            return HttpResponse(request.session['username'])

     2.多继承(继承顺序从左到右)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class BaseView(object):
        def dispatch(self, request, *args, **kwargs):
            if request.session.get('username'):
                response = super(BaseView,self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')
      
    class IndexView(BaseView,View):#先去找BaseView,BaseView中未定义在去找View
      
        def get(self,request,*args,**kwargs):
            return HttpResponse(request.session['username'])

     CBV第二种方式装饰器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    from django.utils.decorators import method_decorator
      
    def auth(func): #定义装饰器
        def inner(request,*args,**kwargs):
            if request.session.get('username'):
                obj = func(request,*args,**kwargs)
                return obj
            else:
                return redirect('/login.html')
        return inner
      
    @method_decorator(auth,name='get')  #放在类顶部就需要method_decorator这个装饰器
    class IndexView(View):
      
        @method_decorator(auth) #放在dispatch上就相当于全局都需要经过认证
        def dispatch(self, request, *args, **kwargs):
            if request.session.get('username'):
                response = super(IndexView,self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')
      
        @method_decorator(auth)
        def get(self,request,*args,**kwargs):
            return HttpResponse(request.session['username'])
      
        @method_decorator(csrf_exempt)  # 无效 csrf 放到post函数上的装饰器,是无效的,需要放到dispath上或者类上
        def post(self,request,*args,**kwargs):
            return HttpResponse(request.session['username'])

     四.中间件middleware

    如下是django的生命周期

     如下为中间件的执行顺序

     - 中间件执行时机:请求到来,请求返回时
      - 中间件是一个类:
      def process_request(self,request):
        print('m2.process_request')

      def process_response(self,request, response):
        print('m2.prcess_response')
        return response

        - 应用:
        - 请求日志
        - 用户登录认证

    Django根目录新建md文件夹,新建Middleware.py文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from django.utils.deprecation import MiddlewareMixin
     
    class M1(MiddlewareMixin):
        '''先执行request,然后到url路由,url之后返回到最上方,在执行view,如果出现错误就直接到response上,执行完,到真正到视图,如果有问题就
        执行exception,从下至上查找,如果找到exception就直接执行exception的return在走response返回用户
        每个中间件中,4个方法不需要都写.
        '''
        def process_request(self,request):
     
            if request.path_info == "/login.html":
                return None
            user_info = request.session.get("username")
            if not user_info:
                return redirect("/login.html")

     注:新的django版本可能不存在MiddlewareMixin,需要手动写一下这个类进行继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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):
     
            if request.path_info == "/login.html":
                return None
            user_info = request.session.get("username")
            if not user_info:
                return redirect("/login.html")

     settings里配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'md.Middleware.M1',
    ]
     
    WSGI_APPLICATION = 'BBS.wsgi.application'
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 引擎(默认)
     
    SESSION_COOKIE_NAME = "sessionid"  # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"  # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None  # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False  # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True  # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600  # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = True  # 是否每次请求都保存Session,默认修改之后才保存(默认)
  • 相关阅读:
    【TCP/IP】【网络基础】网页访问流程
    【linux】【rpm】确定程序是否 rpm 安装
    【linux】【CPU】【x86】平台说明
    【linux】【进程】stand alone 与 super daemon 区别
    【内存】堆内存和栈内存
    【英语】【音标】元音字母 和 开音节 闭音节
    【php】【异步】php实现异步的几种方法
    【操作系统】多处理器系统的用户模式和特权模式
    张量漫谈(第三篇)
    张量漫谈(前两篇)
  • 原文地址:https://www.cnblogs.com/ExMan/p/9473814.html
Copyright © 2011-2022 走看看