高级装饰器---验证用户登录
需求
1、公司又很多网站,每个页面用一个函数来代替,之前任何人都能登入。
2、现在要改变每个页面的功能,其中有两个页面需要验证用户登录。
3、页面功能:a、首页不需要登录;b、home页面和bbs页面需要登录。
代码1、带函数返回值的装饰器:
1、问题1:原码中调用home时,会有返回值"from home"的,但是在装饰器过程中,return返回值会没有。
2、解决方式:由于home是在func的时候调用的,所以需要在func后面定义个变量,print返回结果。
1 def auth(func): 2 def wrapper(*args,**kwargs): 3 username = input("username:").strip() 4 password = input("password:").strip() 5 6 if user==username and passwd == password: 7 print("\033[32;1mUser has passed authentication\033[0m") 8 #func(*args,**kwargs) #没有返回值的时候用 9 #return func(*args,**kwargs) #如果函数在这里结束了,就可以return。 10 res = func(*args,**kwargs) #也可以赋值变量,然后做其他的修饰,最后在return返回。 11 print("the home is return: %s" % res) 12 return res #调用函数home时,可以返回值 13 else: 14 exit("\033[31;1mInvalid username or password\033[0m") 15 16 return wrapper 17 18 19 def index(): 20 print('welcome to index page') 21 22 @auth 23 def home(): 24 print('welcome to home page') 25 return "from home" #原代码中是有返回值的。 26 27 @auth 28 def bbs(): 29 print('welcome to bbs page') 30 31 32 index() 33 print(home()) #原代码可以继续调用函数的返回值 34 bbs()
多种权限认证
1、用一个函数体实现多种方式进行认证:
2、模拟本地用户名和密码和ldap用户认证密码:
1 #!/usr/bin/env python 2 # -*- coding:utf8 -*- 3 # Author:Dong Ye 4 5 6 import time 7 user,passwd = 'dy','asd' 8 #装饰器 9 def auth(auth_type): #定义一个装饰器标签函数,auth_type是装饰器的标签(auth_type = "local" & auth_type="ldap") 10 print("auth func:",auth_type) 11 def outer_wrapper(func): #定义接收@auth传过来的home的内存地址,并赋值给func 12 def wrapper(*args,**kwargs): #定义嵌套函数,做功能装饰home() & bbs(),并且home(args1) & bbs(args1)的参数会传到这里 13 #print("wrapper func args:",*args,**kwargs) 14 if auth_type == 'local': 15 username = input('username: ').strip() 16 password = input('password: ').strip() 17 if user == username and passwd == password: 18 print("\033[32;1mUser has passed authentication\033[0m") 19 return func(*args,**kwargs) #执行源代码home() & bbs(),并且home(args1) & bbs(args1)的参数会传到这里 20 else: 21 exit("\033[31;1mInvalid username or password\033[0m") 22 23 elif auth_type=='ldap': 24 print('是以ldap的方式登录') 25 return wrapper 26 return outer_wrapper 27 28 #注释: 29 #home----传参:内存地址和装饰器标签(local&ldap)----> auth(解封装),auth_type=装饰器标签 -----home的内存参数---->outer_warpper(解封装),func= home---->调用wrapper(*args,**kwargs)-->func函数func(*args,**kwargs)=home(*args,**kwargs) 30 #wrapper ----内存地址1---->outer_wrapper----内存地址1和2---->auth--内存地址(1、2)通过装饰器标签(local&ldap)---->home重新赋值 31 def index(): 32 print('welcome to index page') 33 34 #原代码 35 #home认证用本地认证 36 #auth_type = "local" 赋值给了auth(auth_type) 37 #@auth home = auth(outer_wrapper(func)) func = home 38 #通过高阶函数的功能将wrapper的内存地址返回给outer_wrapper 39 #最后将outer_wrapper的内存地址返回给auth函数,并重新赋值给home 40 @auth(auth_type = "local") 41 def home(): 42 print('welcome to home page') 43 return "from home" 44 45 46 #bbs用远程的ldap 47 @auth(auth_type="ldap") #bbs = auth(bbs) 48 def bbs(): 49 print('welcome to bbs page') 50 51 52 53 54 55 #原调用 56 index() 57 home() #其实执行的是通过wraooer、outer_warpper、auth返回的内存地址,找到wrapper函数体执行的 58 bbs()