flask实现token登录验证及跨域问题options请求问题

本文主要展示如何用flask实现token验证及跨域问题,本文主要参考文章为:Flask实现token认证 - 简书

但基于此,更详细的实现了包括解决频繁options问题、全局请求token验证问题。

run.py

代码中分隔符(======)后的可以略过。

from flask import Flask, g, jsonify, redirect, request, make_response
from flask_httpauth import HTTPBasicAuth
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from itsdangerous import BadSignature, SignatureExpired
from flask_cors import CORS
import mysql.connector as mc
import configparser
import re

# 读取配置文件
config = configparser.ConfigParser()
config.read('config.conf', encoding='utf8')

SECRET_KEY = config['SECRET_KEY']['SECRET_KEY']
db_host = config['db']['host']
db_database = config['db']['database']
db_user = config['db']['user']
db_password = config['db']['password']

app = Flask(__name__)
CORS(app, supports_credentials=True, max_age=6000)  # max_age设置全局请求的Options预检请求最长时间600s
auth = HTTPBasicAuth()


@app.before_request
@auth.login_required
def is_login():
    # print("start")

    # 如果是login,可以通过白名单,获取的token后续可以放在自定义请求头里
    if request.path == '/login':
        return None

    if request.method == 'POST':
        # print("POST")
        return None

    if request.method == 'GET':
        # print("GET")
        return None


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


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


# 连接数据库操作,查看保存的用户名和密码
def connect(user_name, password):
    conn = mc.connect(host=db_host, user=db_user, passwd=db_password, database=db_database)
    cursor = conn.cursor(dictionary=True)
    args = (user_name, password)
    verify_sql = "SELECT user_name FROM account WHERE user_name = %s AND password = %s;"
    cursor.execute(verify_sql, args)
    user = cursor.fetchone()
    # print(user)
    conn.close()
    return user


# 验证token
@auth.verify_password
def verify_password(username, password):
    # 先验证token
    user_id = re.sub(r'^"|"$', '', username)
    user_id = verify_auth_token(user_id)

    if not user_id:  # 如果token不存在,验证用户id与密码是否匹配
        user_id = connect(username, password)
        # 如果用户id与密码对应不上,返回False
        if not user_id:
            return False
        else:  # 如果用户名与密码匹配,则把用户名存到g.user_id这个全局变量里去,后续数据查询可用
            g.user_id = user_id.get('user_name')
            # print("数据库查询结果:")
            # print(g.user_id)
            return True
    if user_id:  # 如果token存在,则将token验证返回的user_name数据存到g.user_id这个全局变量里去,后续数据查询可用
        g.user_id = user_id.get('user_name')
        # print("传入的不是用户名是token:")
        # print(g.user_id)
        return True


@app.route('/login', methods=['GET'])
@auth.login_required
def login():
    token = generate_auth_token(g.user_id)
    return jsonify({'token': str(token)})


@app.route('/index')
def index():
    return None


@app.route('/logout')
def logout():  # 用来做登出用,后端返回200前端清除token。
    return "200"


@app.route('/getUserInfo', methods=['GET'])
def getUserInfo():  # 用来做后端鉴权用,如果返回200说明鉴权通过。
    # print("/getUserInfo  start")
    # if g.user_id:
    #     print("this getUserInfo user_id:  "+g.user_id)
    return "200"


# ==============================================================================
# 以下把消息推送功能(msg)实现api,后续再优化后端代码结构

@app.route('/msg/handleCreate', methods=['POST'])
def msg_handleCreate():  # 创建消息推送配置,参数待定
    # print("/getUserInfo  start")
    return "200"


@app.route('/msg/handleLook', methods=['GET'])
def msg_handleLook():  # 查看消息推送配置,参数待定,后端分页,后端返回json数组
    # print("/getUserInfo  start")
    return "200"


@app.route('/msg/handleEdit', methods=['POST'])
def msg_handleEdit():  # 编辑消息推送配置,参数待定
    # print("/getUserInfo  start")
    return "200"


@app.route('/msg/handleDelete', methods=['POST'])
def msg_handleDelete():  # 删除消息推送配置,参数待定
    # print("/getUserInfo  start")
    return "200"


if __name__ == '__main__':
    app.run()

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值