Flask实现密码登录以及token验证

下面主要完成的是通过Flask实现密码登录,用户成功登录之后,后端返回一个token。此后用户通过token即可访问其他需要验证的网站。

Flask实现密码登录

首先安装所需的模块:

1
2
pip install flask_httpauth
pip install itsdangerous

之后创建一个工具对象utils/MyToken.py,用于生成token以及验证token(通过捕获不同的错误来确定token的状态:正确、错误、过期等):

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
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from itsdangerous import BadSignature, SignatureExpired

SECRET_KEY = 'xxxxxxx' # 这里可以设置密钥


class Token:

# 生成token,有效时间为60min,3600s
@staticmethod
def generate_auth_token(user_id, expiration=3600):
s = Serializer(SECRET_KEY, expires_in=expiration)
return s.dumps({'user_id': user_id}).decode()

# 解析token
@staticmethod
def verify_auth_token(token):
s = Serializer(SECRET_KEY)
try:
# token正确
data = s.loads(token)
return data
except SignatureExpired:
# token过期
print("token已经过期")
return None
except BadSignature:
# token错误
print("token错误")
return None

之后在Flask前端进行相应的验证配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from flask import Flask, jsonify, g, request, abort, make_response, send_from_directory
from flask_cors import CORS
from flask_httpauth import HTTPBasicAuth
from utils.MyToken import Token

auth_user = HTTPBasicAuth() # 用户名和密码验证

# 用户名和密码验证
@auth_user.verify_password
def verify_password(username, password):
# 验证用户id与密码是否匹配
label, auth = db.hasUser(username, password)
# 如果用户id与密码对应不上,返回False
if not label:
return False
g.user_id = username
g.user_auth = auth
return True

用户名和密码验证主要是使用HTTPBasicAuth,在postman的测试中,指定路径为Authorization -> Basic Auth。通过verify_password函数来指定验证方式。其中hasUser函数是自己写的函数,可以通过连接数据库,并通过给定的username和password来判定用户id和密码是否匹配,如果匹配,则返回True,否则返回False。

然后在需要用户密码验证的链接之前增加修饰:@auth_user.login_required

如下,完成登录链接的逻辑:

1
2
3
4
5
6
7
# 登录验证
@app.route('/login', methods=['POST'])
@auth_user.login_required
def login():
user = g.user_id
token = Token.generate_auth_token(g.user_id)
return jsonify({'token': token})

如果用户访问该链接,会首先进行auth_use的验证,只有当验证返回True的时候才会进入login函数。login函数中返回token给前端。

Flask实现token验证

token验证的实现与前面类似,同样是通过实现验证函数来完成。token验证主要是使用HTTPTokenAuth,在postman的测试中,指定路径为Authorization -> Bearer Token

1
2
3
4
5
6
7
8
9
10
from flask_httpauth import HTTPTokenAuth

auth_token = HTTPTokenAuth() # token验证

# token验证
@auth_token.verify_token
def verify_token(token):
token = re.sub(r'^"|"$', '', token)
label = Token.verify_auth_token(token)
return label

然后在需要token验证的链接之前增加修饰:@auth_token.login_required

1
2
3
4
5
6
# 获取数据
@app.route('/data', methods=['GET'])
@auth_token.login_required
def allData():
data = db.getData()
return data

与前端axios的对接

前端axios完成用户密码的传递(通过auth指定),这里的密码使用md5加密是为了进行演示,实际情况下一般不会使用md5进行密码的加密:

1
2
3
4
5
6
7
8
9
10
11
let toParams = {
username: this.param.username.toString(),
password: md5(this.param.password).toUpperCase(),
}

//向后端发送登录请求
this.$axios({
method: 'POST',
url: this.$store.state.backend_url + 'login',
auth: toParams,
})

前端axios完成token的传递(一般是通过axios的拦截器完成):

1
2
3
4
5
6
7
8
9
10
$axios.onRequest(config => {
return new Promise((resolve, reject) => {
//match api
let token = app.$cookies.get('token');
//add token
if (token) config.headers.Authorization = 'Bearer ' + token;
//其他的请求前业务逻辑 比如:api map
resolve(config);
})
});

这里涉及到cookies和axios拦截器的使用,内容可以查看相关文章。

参考文章

  1. Flask实现token认证 - -零 - 博客园 (cnblogs.com)

Flask实现密码登录以及token验证
http://example.com/2022/02/12/Flask实现密码登录以及token验证/
作者
EverNorif
发布于
2022年2月12日
许可协议