博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python装饰器 & flask 通过装饰器 实现 单点登录验证
阅读量:4970 次
发布时间:2019-06-12

本文共 4214 字,大约阅读时间需要 14 分钟。

首先介绍装饰器,以下是一段标注了特殊输出的代码。用于帮助理解装饰器的调用过程。

 

import time    def Decorator_one(arg1):      info = "\033[1;31;40mthis is Decorator_one with para " + str(arg1)      print(info)      def _Decorator_one(func):          print('\033[1;31;40mthis is _Decorator_one')          def __Decorator_one(*args, **kwargs):              def __exit__():                  print('exit###############')              print('\033[1;31;40mthis is __Decorator_one')              start = time.time()              return_value = func(*args, **kwargs)              end = time.time()              result = "\033[1;31;40mDecorator: " + str((end-start) * 1000)              print(result)              print('\033[1;31;40m__Decorator_one will end')              return 'deco1'          print('\033[1;31;40m_Decorator_one will end')          return __Decorator_one      print('\033[1;31;40mDecorator_one will end')      return _Decorator_one      def Decorator_two(arg2):      info = "\033[1;32;40mthis is Decorator_two with para " + str(arg2)      print(info)      def _Decorator_two(func):          print('\033[1;32;40mthis is _Decorator_two')          def __Decorator_two(*args, **kwargs):              print('\033[1;32;40mthis is __Decorator_two')              start = time.time()              return_value = func(*args, **kwargs)              end = time.time()              result = "\033[1;32;40mDecorator: " + str((end-start) * 1000)              print(result)              print('\033[1;32;40m__Decorator_two will end')              return 'deco2'          print('\033[1;32;40m_Decorator_two will end')          return __Decorator_two      print('\033[1;32;40mDecorator_two will end')      return _Decorator_two    @Decorator_one(True)  @Decorator_two(False)  def testfunc(para):      print "\033[1;37;40mstart"      time.sleep(0.1)      print "\033[1;37;40mend"      return '123'      if __name__ == '__main__':      aaa = testfunc(123)      print(aaa)

程序输出如下图

 

 

简单介绍一下上面的运行情况:

首先,声明装饰器的结构分为两层。如果装饰器需要包含参数,为了处理参数则分为三层。上述代码的例子则使用了三层。

最外层参数即是装饰器参数;中间层参数为被修饰的方法的方法名;最内层为被修饰的方法的参数。可在各层处理参数。

装饰器的调用顺序第一次见到的时候觉得很诡异。可以理解为两个装饰器的三层结构是并行走下去的。具体顺序见图,就不细说了。

最后,被装饰器修饰过的函数,调用之后的返回值是最后一个调用的装饰器,最内层定义函数的返回值。所以请一定记得,对被修饰函数返回值的处理,要在装饰器中完成。

 

 

以下是flask通过装饰器实现单点登录验证的方法:

单点登录的简单概念

多个网站通过同一套用户权限进行登录验证的手段。网站可以在同一个子域或跨域。这里的方法不涉及跨域。

登录及验证方法为,提供登录验证的网站在登录成功后,生成一个token添加到cookie中,用于验证用户权限。

同二级域名下的网站,或者跨域的网站,可以通过访问登录验证的网站这个子域,获取cookie中的token字段,向登录验证的网站验证权限。

代码最初是公司前辈实现的,这里呢主要是觉得如果使用调用函数的方式,在方法中验证登录非常麻烦,按照装饰器的风格改造了一下。

 

登录校验装饰器的实现(伪代码)(2017-06-07修改,见注释)

 

import requestfrom flask import session, request, redirectdef do_ssoh(route=""):# 删去route=""    def _do_sso(func):        def __do_sso(*args, **kwargs):            # 通过request模块的cookies方法获取cookie中的信息            如果request.cookies方法有token这个key                token = request.cookies['token'].encode('utf-8')            否则跳转到sso登录页面:                return redirect(sso_url + "http://" + domain + route)#route 替换为 request.path            # 通过request模块的header方法或remote_addr方法,获取用户真实ip            client_ip = request.headers.get('X-Forwarded-For', '')            if not client_ip:                client_ip = request.remote_addr            # 去sso站点检查token是否有效            try:                result = do_post(sso_url, '...token...')            检查访问失败则跳转到sso登录页面:                return redirect(sso_url + "http://" + domain + route)#route 替换为 request.path            如果检查通过,则在session中保存用户名:                session['username'] = result['result']['name']                return func()            否则跳转到登录页面:                return redirect(sso_url + "http://" + domain + route)#route 替换为 request.path        return __do_ssoauth    return _do_sso

装饰器的使用(2017-06-07修改,见注释)

 

 

@app.route('/index')  @account.do_ssoauth('/index')  #删去参数def index():      response = make_response(render_template(          "/index.html",          username=session['username']))      return response

 

 

这样,访问xxx/index的时候就会去sso站点验证是否登录。

关于跨域的实现暂时没有需求,也就没有去做。个人以为,需要前端配合,添加跨域访问的js代码,去获取sso所在子域下的cookie,再去sso站点验证。不确保思路正确哦~。

 

2017-06-07修改原因:在项目中使用了flask 蓝图的动态url前缀之后,其实参数是不太能良好的配置为访问的url。尤其是在g需要一个运行时的上下文环境的时候(就是在运行时才有这个量),而程序已开始跑,就会把这个装饰器注册(or what?),这时候g变量其实不存在。现修改为不需要参数,在装饰器中使用request.path来获取请求路径(其实一开始就该想到这里)

 

转载于:https://www.cnblogs.com/blaketairan/p/7136732.html

你可能感兴趣的文章
python-----删除空文件夹
查看>>
camel
查看>>
传输层——TCP报文头介绍
查看>>
Linux内核超时检测
查看>>
集合栈计算机 (The SetStack Computer,ACM/ICPC NWERC 2006,UVa12096
查看>>
windows 下安装docker依赖boot2docker镜像默认用户和密码
查看>>
【120525】北约芝加哥峰会的重要议题:阿富汗
查看>>
sqlite之WAL模式
查看>>
ASP.NET常用的指令
查看>>
F#基础教程 直接量
查看>>
Sd - JavaBase问题
查看>>
利用CSS让dl dt dd呈现多行多列效果
查看>>
【译著】第9章 SportsStore:管理 — 《精通ASP.NET MVC 3框架》
查看>>
判断文件类型
查看>>
python-GIL、死锁递归锁及线程补充
查看>>
.Net服务组件(ServicedComponent)简介及其使用
查看>>
Binding介绍
查看>>
JQuery实现可编辑的表格
查看>>
bzoj4903 [Ctsc2017]吉夫特
查看>>
java线程学习之wait方法
查看>>