You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中重定向时如何携带JWT认证头访问受保护路由?

问题分析与解决方案

你当前的核心问题是:redirect函数的headers参数是用来设置响应的HTTP头,而非浏览器发起重定向请求时携带的请求头。浏览器执行重定向时,只会自动携带Cookie这类同源凭证,不会将响应头中的Authorization信息传递到新请求里。

以下是几种可行的解决方案:

方案一:将JWT存入HttpOnly Cookie(推荐)

利用浏览器自动携带Cookie的特性,将token存入HttpOnly Cookie(可避免XSS攻击),再让受保护路由从Cookie中提取token完成验证。

修改登录路由

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = TestLogin()
    if form.is_submitted():
        req = requests.post('http://127.0.0.1:5000/login', json={"email": form.login.data, "senha": form.senha.data})
        if req.json()['auth'] == True:
            token = create_access_token(identity=form.login.data)
            # 生成重定向响应并设置安全Cookie
            response = redirect(url_for('membros'))
            response.set_cookie(
                'access_token',
                value=f'Bearer {token}',
                httponly=True,  # 禁止JS读取,防XSS
                secure=True,    # 生产环境开启,仅HTTPS传输
                samesite='Lax'  # 降低CSRF风险
            )
            return response
    return render_template('test.html', form=form)

自定义JWT验证装饰器

让原@jwt_required()能从Cookie中读取token:

from functools import wraps
from flask_jwt_extended import verify_jwt_in_request, get_jwt_identity
from flask import request

def jwt_required_from_cookie():
    def wrapper(fn):
        @wraps(fn)
        def decorator(*args, **kwargs):
            # 从Cookie取token并注入请求头,适配原JWT验证逻辑
            token = request.cookies.get('access_token')
            if token:
                request.headers['Authorization'] = token
            verify_jwt_in_request()
            return fn(*args, **kwargs)
        return decorator
    return wrapper

# 用自定义装饰器保护路由
@app.route('/membros')
@jwt_required_from_cookie()
def membros():
    current_user = get_jwt_identity()
    return f"欢迎访问受保护页面,{current_user}!"

方案二:URL参数传递(仅测试用,禁止生产环境使用)

将token作为URL参数传递,受保护路由从参数中提取验证。但此方法会导致token暴露在地址栏、历史记录中,存在严重安全风险。

修改登录路由

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = TestLogin()
    if form.is_submitted():
        req = requests.post('http://127.0.0.1:5000/login', json={"email": form.login.data, "senha": form.senha.data})
        if req.json()['auth'] == True:
            token = f'Bearer {create_access_token(identity=form.login.data)}'
            return redirect(url_for('membros', token=token))
    return render_template('test.html', form=form)

修改受保护路由

from flask_jwt_extended import decode_token, get_jwt_identity

@app.route('/membros')
def membros():
    token = request.args.get('token')
    if not token:
        return redirect(url_for('login'))
    # 手动验证token
    try:
        decode_token(token.replace('Bearer ', ''))
        current_user = get_jwt_identity()
        return f"欢迎访问受保护页面,{current_user}!"
    except:
        return redirect(url_for('login'))

方案三:前端存储token并发起AJAX请求

若页面需要动态加载内容,可将token注入页面JS,通过AJAX请求受保护API时携带Authorization头:

修改登录路由

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = TestLogin()
    if form.is_submitted():
        req = requests.post('http://127.0.0.1:5000/login', json={"email": form.login.data, "senha": form.senha.data})
        if req.json()['auth'] == True:
            token = f'Bearer {create_access_token(identity=form.login.data)}'
            # 将token传入模板
            return render_template('membros.html', token=token)
    return render_template('test.html', form=form)

在membros.html中添加JS

<script>
const token = "{{ token }}";
// 发起AJAX请求获取受保护数据
fetch('/api/membros', {
    headers: {
        'Authorization': token
    }
})
.then(res => res.json())
.then(data => {
    // 处理并渲染数据
    console.log(data);
});
</script>

内容的提问来源于stack exchange,提问作者Gustavo Nunes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:10:15