如何从Flask设置cookie并传递给ReactJS

3

我正在开发一个项目,使用flask作为后端和reactjs作为前端。当我尝试从flask设置cookie时,浏览器上没有设置cookie。我一直在研究可能有什么问题。在flask中,我有一个端点/login,当用户从reactjs登录时,会创建一个JWT并设置一个cookie。我的flask应用程序在端口5000上运行,而我的react应用程序在端口3000上运行。在解决这个问题的过程中,我遇到了许多解决方案,但它们仍然无法解决问题,例如设置CORS(app,support_credentials=True)以及在设置cookie时包括domain关键字参数
下面是来自我的flask应用程序的代码:

# login route - this will set cookie (JWT token)
@app.route('/login', methods=['POST'])
@cross_origin()
def login():
    auth = request.authorization

    # the auth should have a username and a password
    user = User.query.filter_by(username=auth['username']).first()

    if not user:
        return jsonify({'msg': 'user not found'}), 404

    if bcrypt.check_password_hash(user.password, auth['password']):
        # generate a token
        access_token = create_access_token(identity=user.username, expires_delta=datetime.timedelta(days=1))
        
        response = make_response({'msg': 'successfully logged in!'})
        response.headers['Access-Control-Allow-Credentials'] = True
        response.set_cookie('access_token', value=access_token, domain='127.0.0.1:3000')

        # we need to convert the response object to json

        return jsonify({'response': response.json}), 200

    return jsonify({'msg': 'wrong credentials'}), 401
2个回答

3
我找出了问题所在。在细节之前,这里有两个很棒的视频,解释了CORS以及如何使用它们。 上述两个教程并不特定于Flask,但它们与Flask相关,我们使用flask-cors库来允许CORS。从我的代码中可以看到,我有一个/login端点,如果用户登录,则会生成一个响应对象并设置包含JWT的cookie。这里的重点是@cross_origin()装饰器,这是使CORS可能的关键。但是在这里我们仍然需要设置一些参数,其中最重要的是support_credentials=True。默认情况下,Flask-CORS不允许在站点间提交cookie,因为这可能存在安全隐患。要允许跨源发送cookie或认证请求,只需将supports_credentials选项设置为True即可。对于我的代码,这就是我添加的内容。
@cross_origin(methods=['POST'], supports_credentials=True, headers=['Content-Type', 'Authorization'], origin='http://127.0.0.1:5500')

当然,即使在这之后,它仍然没有工作,并且有一个原因。我没有返回包含所有标头的实际响应对象。从我的代码来看,我需要改变的另一件事是:
return jsonify({'response': response.json}), 200

to

return response, 200

为了测试目的,我创建了另一个简单的端点/user,它仅返回存储在浏览器上的cookie。
@app.route('/user')
@cross_origin(supports_credentials=True)
def get_user():
    response = make_response('cookie being retrieved!')
    cookie = request.cookies.get('access_token')
    return jsonify({'cookie': cookie})

了解如何配置前端以处理请求也很重要。下面是我开发的一个简单的JavaScript代码,用于使用fetch API测试API。

// for logging in a user
fetch('http://127.0.0.1:5000/login', {
                headers: {'Authorization': 'Basic ' + btoa(`${username}:${password}`)}, // the values of username and password variables are coming from a simple login form
                method: 'POST',
                mode: 'cors' // here we specify that the method is CORS meaning that the browser is allowed to make CORS requests
            })
            .then(res => res)
            .then(data => console.log(data))

// for getting the cookies - testing
                fetch('http://127.0.0.1:5000/user', {
                method: 'GET',
                mode: 'cors',
                credentials: 'include' // includes cookies, authorization in request headers
            })
            .then(res => res.json())
            .then(msg => console.log(msg))

我希望这能帮助到其他人 :)

1

我也遇到过这个问题,你需要做的是在你的React项目中的package.json文件中添加以下内容:

proxy : http://localhost:5000

或每当您的Flask应用程序运行时。

然后它使应用程序一起运行并解决您的问题。

现在,当您获取时,需要像这样获取:

fetch("/user")

而不是

fetch("http://localhost5000/user")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接