zoukankan      html  css  js  c++  java
  • Flask实现token认证

    1. 安装

    pip install flask_httpauth
    pip install itsdangerous
    

    2. 创建对象

    from flask import Flask, g, jsonify
    from flask_httpauth import HTTPBasicAuth
    
    
    app = Flask(__name__)
    auth = HTTPBasicAuth()
    

    3. 生成token

    from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
    
    # 密钥,可随意修改
    SECRET_KEY = 'abcdefghijklmm'
    # 生成token, 有效时间为600min
    def generate_auth_token(user_id, expiration=36000):
        # 第一个参数是内部私钥
        # 第二个参数是有效期(秒)
        s = Serializer(SECRET_KEY, expires_in=expiration)
        return s.dumps({'user_code': user_code})
    

    4. 解析token

    from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
    from itsdangerous import BadSignature, SignatureExpired
    
    
    # 密钥,可随意修改
    SECRET_KEY = 'abcdefghijklmm'
    # 解析token
    def verify_auth_token(token):
        s = Serializer(SECRET_KEY)
        # token正确
        try:
            data = s.loads(token)
            return data
        # token过期
        except SignatureExpired:
            return None
        # token错误
        except BadSignature:
            return None
    

    5. 验证token

    # 数据库配置
    db = {
            'host': '127.0.0.1',
            'user': 'root',
            'password': 'admin123',
            'port': 3306,
            'database': 'school',
            'charset': 'utf8'
    }
    
    
    # 连接数据库操作
    def connect(user_id, password):
        conn = mc.connect(**db)
        cursor = conn.cursor(dictionary=True)
        args = (user_id, password)
        verify_sql = "SELECT user_id FROM account WHERE user_id = %s AND pwd = PASSWORD(%s);"
        cursor.execute(verify_sql, args)
        user = cursor.fetchone()
        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)
        # 如果token不存在,验证用户id与密码是否匹配
        if not user_id:
            user_id = connect(username, password)
            # 如果用户id与密码对应不上,返回False
            if not user_id:
                return False
        g.user_id = user_id.get('user_id')
        return True
    

    6. 完整代码

    配置文件config.py

    # 数据库配置
    db = {
            'host': '127.0.0.1',
            'user': 'root',
            'password': 'admin123',
            'port': 3306,
            'database': 'school',
            'charset': 'utf8'
    }
    
    # 密钥,可随意修改
    SECRET_KEY = 'abcdefghijklmm'
    

    主文件run.py

    from flask import Flask, g, jsonify
    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
    from config import db, SECRET_KEY
    import re
    
    
    app = Flask(__name__)
    CORS(app, supports_credentials=True)
    auth = HTTPBasicAuth()
    
    
    # 生成token, 有效时间为600min
    def generate_auth_token(user_id, expiration=36000):
        s = Serializer(SECRET_KEY, expires_in=expiration)
        return s.dumps({'user_id': user_id})
    
    
    # 解析token
    def verify_auth_token(token):
        s = Serializer(SECRET_KEY)
        # token正确
        try:
            data = s.loads(token)
            return data
        # token过期
        except SignatureExpired:
            return None
        # token错误
        except BadSignature:
            return None
    
    
    # 连接数据库操作
    def connect(user_id, password):
        conn = mc.connect(**db)
        cursor = conn.cursor(dictionary=True)
        args = (user_id, password)
        verify_sql = "SELECT user_id FROM account WHERE user_id = %s AND pwd = PASSWORD(%s);"
        cursor.execute(verify_sql, args)
        user = cursor.fetchone()
        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)
        # 如果token不存在,验证用户id与密码是否匹配
        if not user_id:
            user_id = connect(username, password)
            # 如果用户id与密码对应不上,返回False
            if not user_id:
                return False
        g.user_id = user_id.get('user_id')
        return True
    
    
    @app.route('/login')
    @auth.login_required
    def login():
        token = generate_auth_token(g.user_id)
        return jsonify({'token': token})
    
    
    @app.route('/index')
    @auth.login_required
    def index():
        return 'index'
    
    
    if __name__ == '__main__':
        app.run()
    
    

    只需要在需要登录验证请求下添加装饰器@auth.login_required即可

    7. 测试

    我这里使用到的数据库是school其中的account
    该表有两个字段user_idpwd
    先向表中添加一条数据进行测试
    INSERT INTO account (user_id, password) VALUES("kun", PASSWORD("admin123"))

    • 直接输入路由测试

    返回401错误码


     
     
    • 输入错误的用户名或者密码测试

    返回401错误码


     
     
    • 输入正确的用户名以及密码测试

    输入正确的用户名以及密码后,测试成功,获取到token
    前端可以将token存入到浏览器session
    下次发请求加上token,即可通过验证

     
     
    • 使用有效的token测试

    使用刚才生成的token进行测试,测试成功


     
     
    • 使用过期的token或者错误的token测试

    返回401错误码


     
     

    8. 总结

    1. flask_httpauth用于获取请求中的Authorization参数
    2. itsdangerous用于生成以及验证token
    3. SECRET_KEY密钥可自行修改
    4. 用户可以使用用户密码进行认证,或者使用token进行认证
    5. 在需要token认证的路由前添加@auth.login_required即可开启认证
    6. 可以在before_request处理程序中使用@auth.login_required修饰器, 应用到所有请求



    作者:无敌小鲁班
    链接:https://www.jianshu.com/p/a360473bc9ab

  • 相关阅读:
    memcached整理の基本使用
    memcached整理の编译
    linux命令の删除文件和文件夹 复制粘贴文件和文件夹
    ANSIBLE工具
    RSYNC服务
    FTP服务
    Mac运维安装软件
    WebSocket协议
    TCP三次握手和四次挥手、HTTP协议
    GITBOOK/HEXO TRAVIS GITHUB-PAGES 博客搭建
  • 原文地址:https://www.cnblogs.com/-wenli/p/14016905.html
Copyright © 2011-2022 走看看