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

    一.什么是session

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

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

    认证装饰器:

    # 登陆验证
    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
    

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

    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实例化的对象,任何属性优先从自己里面找,找不到在去父类里找)

    class A(object):
        def aaa(self):
            print('from A')
        def bbb(self):
            self.aaa()
     
    class B(A):
        def aaa(self):
            print('from B')
     
    c = B()
    c.aaa()
    

    应用:

    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.多继承(继承顺序从左到右)

    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第二种方式装饰器

    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文件

    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,需要手动写一下这个类进行继承

    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里配置:

    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,默认修改之后才保存(默认)
    
  • 相关阅读:
    Window 窗口类
    使用 Bolt 实现 GridView 表格控件
    lua的table库
    Windows编程总结之 DLL
    lua 打印 table 拷贝table
    使用 xlue 实现简单 listbox 控件
    使用 xlue 实现 tips
    extern “C”
    COleVariant如何转换为int double string cstring
    原来WIN32 API也有GetOpenFileName函数
  • 原文地址:https://www.cnblogs.com/Crazy-lyl/p/7613189.html
Copyright © 2011-2022 走看看