Flask 实现HTTP令牌token认证HTTPTokenAuth

前言

  • 命名文件不要用“token.py”,会报无法导入xxx类等异常
  • 在restful设计中,用户认证模式通常使用json web token,而不会使用传统的HTTP Basic认证(传入账号密码)
  • token认证模式如下:在请求header中加入token(传入账号密码)

Flask中的实现

flask扩展flask-httpauth提供了该认证方法

$ pip install flask-httpauth

首先实例化

auth = HTTPTokenAuth(scheme='JWT')

校验token的方法(token_auth.py)

from flask_httpauth import HTTPTokenAuth
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired

from config import Config
from home.libs.error_code import AuthFailed

auth = HTTPTokenAuth(scheme='JWT')


@auth.verify_token
def verify_token(token):
    # Config.SECRET_KEY:内部的私钥,这里写在配置信息里
    s = Serializer(Config.SECRET_KEY)
    try:
        data = s.loads(token)
    except BadSignature:
        # AuthFailed 自定义的异常类型
        raise AuthFailed(msg='token不正确')
    except SignatureExpired:
        raise AuthFailed(msg='token过期')
    # 校验通过返回True
    return True

生成token的方法,放在了modeles.user类中生成

from config import Config
from home import db
from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer



class User(db.Model):
    """用户"""

    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(80), unique=True, nullable=False) # 用户名
    hash_password = db.Column(db.String(120), nullable=False)        # 密码
    phone = db.Column(db.String(20), nullable=False)                 # 手机号

    # 明文密码(只读)
    @property
    def password(self):
        raise AttributeError('不可读')

    # 写入密码,同时计算hash值,保存到模型中
    @password.setter
    def password(self,value):
        self.hash_password = generate_password_hash(value)

    # 检查密码是否正确
    def check_password(self, password):
        return check_password_hash(self.hash_password,password)

    # 生成token
    @staticmethod
    def create_token(user_id):
        """
        生成token
        :param user_id: 用户id
        :return:
        """

        # 第一个参数是内部的私钥,这里写在配置信息里,如果只是测试可以写死
        # 第二个参数是有效期(秒)
        s = Serializer(Config.SECRET_KEY, expires_in=Config.TOKEN_EXPIRATION)
        # 接收用户id转换与编码
        token = s.dumps({"id": user_id}).decode('ascii')
        return token

使用装饰器

from flask import request, jsonify

from home.modles import User


@api.route('/login', methods=['POST'])
def login():
    '''
    接受参数并校验参数,返回token
    :return: 
    '''
    # user = request.json['username']
    # password = request.json['password']
    # guest = User.query.filter_by(username=user).first()
    # # 生成token
    # z_token = User.create_token(guest.id)
    # 
    # return jsonify(token=z_token)
    pass



# 调用该装饰器认证token(导入token_auth.py中的auth:from home.utils.token_auth import auth)
@api.route('/index')
@auth.login_required  
def index():
    return 'helllo word'
posted @ 2020-03-12 17:15  吹神  阅读(8346)  评论(8编辑  收藏  举报