首页 > 解决方案 > Flask 无法验证受保护路由的 JWT 签名

问题描述

我正在尝试使用 JWT 令牌“保护”我的应用程序登录,但似乎我编码或解码错误。为什么它说我有一个无效的签名,虽然 JWT.io 说它是有效的?

我正在我的应用程序初始化中设置密钥,并使用它来编码和解码 JWT 令牌:

#skey = os.urandom(16)
#app.secret_key = f"{skey}"
app.config['SECRET_KEY'] = 'abe535ed6a554fe48e09e111dad2dcbc' #temporary for testing
app.debug = True
print(app.secret_key)

我正在dash使用此功能保护路线:

def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.args.get('token') #http://localhost:5000/route?token={jwttoken}
        if not token:
            return jsonify({'message': 'Token is missing'}), 403
        try:
            data = jwt.decode(token, app.secret_key)
        except jwt.ExpiredSignatureError:
            return jsonify({'message': 'Token expired, log in again'}), 403
        except jwt.InvalidTokenError:
            return jsonify({'message': 'Invalid token. Please log in again.'}), 403
        
        return f(*args, **kwargs)
    return decorated

这是破折号路线:

@app.route('/dash', methods=["GET", "POST"])
@token_required
def dash():
    if 'logged_in' in session:
        if session['logged_in']:
            username = session['username']
            return render_template("dash.html", username=username)
        else:
            return redirect(url_for('home'))
    else:
        return redirect(url_for('home'))

使用正确的详细信息登录时,我的登录路由会重定向到以令牌作为参数的破折号:

@app.route('/login', methods=["GET", "POST"])
def login():
    if request.method == "POST":
        uname = request.form["uname"]
        pswd = request.form["pswd"]
        valid = auth.login(uname, pswd)
        if valid[0]:
            if valid[1]:
                session['username'] = uname
                session['logged_in'] = True
                token = jwt.encode({
                    'user' : uname,
                    'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=60)
                }, 
                app.secret_key)
                return redirect(url_for('dash', token=token))
            else:
               return redirect(url_for('login')) 
        else:
            return redirect(url_for('home'))
    else:
        return render_template("login.html")

但是当我成功登录时,它会重定向到破折号,但总是说我有一个无效的令牌,尽管我已经在jwt.io上验证了它: 在此处输入图像描述在此处输入图像描述

标签: pythonflaskjwt

解决方案


您需要在解码令牌时指定算法。

data = jwt.decode(token, app.secret_key, algorithms=["HS256"])

试试这个它会工作


推荐阅读