简体   繁体   English

如何将 cookie 从烧瓶设置为 reactjs

[英]How to set cookie from flask to reactjs

I am working on a project where I use flask as a backend and reactjs for the front-end.我正在做一个项目,我使用 Flask 作为后端,使用 reactjs 作为前端。 When I try to set a cookie from flask, the cookie is not set on the browser.当我尝试从 Flask 设置 cookie 时,该 cookie 未在浏览器上设置。 I have been researching what could be wrong.我一直在研究什么可能是错的。 I have an endpoint /login in flask where, when the user logs in from reactjs, a JWT is created and a cookie is set.我在烧瓶中有一个端点/login ,当用户从 reactjs 登录时,会创建一个JWT并设置一个 cookie。 My flask app is running on port 5000 and my react app is running on port 3000 .我的烧瓶应用程序在port 5000上运行,我的反应应用程序在port 3000上运行。 During my research on this problem, I came across multiple solutions, but they still did not work, like setting CORS(app, support_credentials=True) and also including the domain keyword argument in set cookie.在我研究这个问题的过程中,我遇到了多种解决方案,但它们仍然不起作用,比如设置CORS(app, support_credentials=True)并在 set cookie 中包含domain keyword argument
Here is the code from my flask app:这是我的烧瓶应用程序中的代码:

# 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

So i figured out whats wrong, before I get into the details, here are two awesome videos that explain CORS and how to work with them所以我弄清楚出了什么问题,在我进入细节之前,这里有两个很棒的视频,它们解释了CORS以及如何使用它们

Now, the above two tutorials are not flask specific, but they are pretty relatable to flask, we use the flask-cors library to allow CORS.现在,以上两个教程不是特定于烧瓶的,但它们与烧瓶非常相关,我们使用flask-cors库来允许 CORS。 from my code, I have a /login endpoint whereby if the user logs in, a response object is made and a cookie containing a JWT is set.从我的代码中,我有一个/login端点,如果用户登录,则创建一个响应对象并设置一个包含 JWT 的 cookie。 The main focus here is the @cross_origin() decorator, this is what makes CORS possible, But in here we still need to set a few things, some kwargs, the most important is the support_credentials=True By default, Flask-CORS does not allow cookies to be submitted across sites, since it has potential security implications.这里主要关注的是@cross_origin()装饰器,这就是使 CORS 成为可能的原因,但是在这里我们仍然需要设置一些东西,一些 kwargs,最重要的是support_credentials=True默认情况下,Flask-CORS 没有允许跨站点提交 cookie,因为它具有潜在的安全隐患。 To allow cookies or authenticated requests to be made cross origins, simply set the supports_credentials option to True.要允许跨域发出 cookie 或经过身份验证的请求,只需将 support_credentials 选项设置为 True。 For my code, this is what I added.对于我的代码,这就是我添加的内容。

@cross_origin(methods=['POST'], supports_credentials=True, headers=['Content-Type', 'Authorization'], origin='http://127.0.0.1:5500')

Of course, even after this, it still did not work and for one reason.当然,即使在此之后,它仍然不起作用,原因之一。 I was not returning the actual response object that contained all the headers.我没有返回包含所有标头的实际响应对象。 From my code, the other thing I had to change was从我的代码中,我必须改变的另一件事是

from

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

to

return response, 200

for testing purposes, I made another simple endpoint /user that simpy returns the cookie that was stored on the browser.出于测试目的,我创建了另一个简单的端点/user ,它 simpy 返回存储在浏览器上的 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})

It is also important to know how to configure the front-end to deal with the requests.了解如何配置前端来处理请求也很重要。 So here is a simple javascript code I developed to test the api, using the fetch api所以这是我开发的一个简单的 javascript 代码来测试 api,使用fetch 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))

I hope this helps somone else :)我希望这对其他人有帮助:)

It happend to me too, what tou need to do is to add to your package.json file on you React project它也发生在我身上,你需要做的是在你的 React 项目中添加到你的package.json文件中

proxy : http://localhost:5000

or whenever your flask app runs on.或者每当您的烧瓶应用程序运行时。

and then it makes the app run together and solves your problem.然后它使应用程序一起运行并解决您的问题。

now, when you fetch you need to fetch like this:现在,当您获取时,您需要像这样获取:

fetch("/user")

and not并不是

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM