flask前后端分离&装饰器

简单的介绍下flask前后端分离的流程,以及部分底层代码。还有装饰器的内容。

流程

前后端分离的大概流程就是这样。

当用户想要登陆时,访问 /api/login

1
2
3
4
5
6
7
8
9
10
11
@app.route('/api/login', methods=['POST'])
@auth.login_required
def get_auth_token():
token = g.user.generate_auth_token()
token = str(token, encoding='utf8')
print(token)
data = {
'token': token,
'username': g.user.username
}
return jsonify(data)

首先,函数会先使用 **@auth.login_required 这个装饰器(关于装饰器的介绍请看下文),跟进 flask_httpauth.py** 看到如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
def login_required(self, f):
@wraps(f)
def decorated(*args, **kwargs):
auth = self.get_auth() # 获取标准验证头(请注意是标准验证)(Basic Auth)
if request.method != 'OPTIONS': # pragma: no cover
password = self.get_auth_password(auth) # 从验证中获取密码

if not self.authenticate(auth, password): # 验证密码
# Clear TCP receive buffer of any pending data
request.data
return self.auth_error_callback() # 密码不对后的验证
return f(*args, **kwargs)
return decorated

主要看一下装饰器内部,先调用了 self.get_auth() 这个函数的作用就是取到 HTTP 头中用于认证的信息。然后进行判断,如果不是 OPTIONS 包的话,就调用 self.get_auth_password 获取到 HTTP 头中标准验证的密码。然后调用 self.authenticate() 来验证密码的准确性。

跟进 self.authenticate() 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def authenticate(self, auth, stored_password):
if auth:
username = auth.username
client_password = auth.password
else:
username = ""
client_password = ""
if self.verify_password_callback: # 如果定义了自己的验证函数,就调用自己的
return self.verify_password_callback(username, client_password)
if not auth:
return False
if self.hash_password_callback: # 如果定义了自己的加密函数,就调用自己的
try:
client_password = self.hash_password_callback(client_password)
except TypeError:
client_password = self.hash_password_callback(username,
client_password)
# 如果没有定义自己的函数,就调用便准验证
return client_password is not None and client_password == stored_password

首先函数会对传进的 auth 进行是否为空的判断。然后判断 self.verify_password_callback 是否为空。这个函数就是你自己定义的密码验证的函数。如下。

1
2
3
4
@auth.verify_password
def verify_password(username_or_token, password):
'''你的验证函数'''
return True

跟进下装饰器。

1
2
3
def verify_password(self, f):
self.verify_password_callback = f
return f

发现这个装饰器就是为 self.verify_password_callback 进行赋值。上面的全部内容就是关于 **@auth.login_required** 的整个流程。

装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def log(text):
print('text is {}'.format(text))

def deractor(func):
print('deractor is running()')
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
return deractor
@log('WARN')
def foo():
print('foo is running')

# 输出
#text is WARN
#deractor is running()

这是因为装饰器的本质就是:foo = log(‘WARN’)(foo) 。对于多个装饰器,如下面代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def a(f):
print(1)
def b(f):
print(2)
def c(f):
print(3)
@a
@b
@c
def d():
pass

# 实际调用运行顺序为
# d = a(b(c(d)))
# 输出为 3 2 1

某些用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class C():
get_password_callback = None
def get_password(self, f):
self.get_password_callback = f
return f

def prints(self):
if self.get_password_callback:
self.get_password_callback()
else:
print(None)
c = C()
c.prints()
@c.get_password
def b():
print(1)
c.prints()

#输出
# None 1