0

我有一个在http://127.0.0.1:5000上运行的烧瓶服务器和一个在 http://localhost:8080 上运行的 vuejs 前端我已经制作了 api 并用邮递员对其进行了测试,一切都按预期工作:(

  • 对 /login 的 POST 请求 -> 登录成功 -> 允许登录用户执行操作)。

    但是当我从 vuejs(使用 axios)发送请求时,cookie 似乎不起作用

  • (对 /login 的 POST 请求 -> 登录成功 -> 无法执行允许登录用户执行的操作(如果会话中的“登录”在烧瓶中为 False))。

烧瓶 API 代码:

app = Flask(__name__)



SESSION_TYPE = 'redis'
app.config.from_object(__name__)
app.config.from_mapping(
    SECRET_KEY='dev'
)
app.config.update(SESSION_COOKIE_SAMESITE="None", SESSION_COOKIE_SECURE=True)
cross_origin(automatic_options=True)
app.config['CORS_HEADERS'] = 'Content-Type'
CORS(app, resources={r"/*": {"origins": "*"}},support_credentials=True)


## configure db
db = yaml.load(open('db.yaml'))
app.config['MYSQL_HOST'] = db['mysql_host']
app.config['MYSQL_USER'] = db['mysql_user']
app.config['MYSQL_PASSWORD'] = db['mysql_password']
app.config['MYSQL_DB'] = db['mysql_db']
mysql = MySQL(app)

## Homepage
@app.route('/index',methods=['GET'])
@cross_origin(supports_credentials=True,origin='http://localhost:8080/')
def index():
    if 'loggedin' in session:
        return jsonify({
            "msg":"user is logged in",
            "data":{
                "username":session['username'],
                "loggedin":True
            },
            "status":200
        })
    else:
        return jsonify({
            "msg":"user is not logged in",
            "data":{
                "username":None,
                "loggedin":False
            },
            "status":200
        })

## LOGIN 
@app.route('/login',methods=['GET','POST'])
@cross_origin(supports_credentials=True,origin='http://localhost:8080/')
def login():
    # print("initial check ",('loggedin' in session))
    if request.method == 'POST':
        req = request.get_json()
        username = req['username']
        password = req['password']
        cur = mysql.connection.cursor()
        if username == "" or password == "":
            return jsonify({
                'msg':'Username and password required',
                'status':401
            })

        user = cur.execute('SELECT * FROM user WHERE username =%s',(username,))
        userdetails = cur.fetchone()
        if user <=0 or not check_password_hash(userdetails[1],password):
            result = {
                'msg':'Incorrect username or password',
                'status':401
            }
            return jsonify(result)
        else:
            session.clear()
            session['username'] = userdetails[0]
            session['loggedin'] = True
            ## print("session username = ",session['username'])
            result = {
                'msg':"Successfully logged in",
                'status':200
            }
            print("inside login <loggedin> = ",('loggedin' in session))
            globallogin = True
            globalusername = userdetails[0]
            return jsonify(result)
            ## return redirect('/index')
    
    return jsonify({
        "msg":"get request at /login",
        "status":200
    }) 

登录.vue:

<template>
<div id = "login">
    <h1>Login page</h1>
    <label>Username</label>
    <input type="text" v-model="username">
    <label>Password</label>
    <input type="password" v-model="password">
    <button v-on:click="login()">Log in</button>
</div>
    
</template>

<script>
import axios from 'axios'
export default {
    data: function(){
        return{
            username:"",
            password:""
        }
    },
    methods:{
        resetform: function(){
            this.username = ""
            this.password = ""
            return
        },
        login: function(){
            const payload = {
                username:this.username,
                password:this.password
            }
            axios.post("http://127.0.0.1:5000/login",payload,{withCredentials: true})
            .then( (data) =>{
                console.log(data)
                if(data.data.status == 401){
                    alert(data.data.msg)
                    this.resetform()
                }
            }).catch( (err) => {
                console.log(err)
            })
        }
        
    },
    mounted() {
        axios.get("http://127.0.0.1:5000/login")
        .then((data)=>{
            console.log(data);
        })
    }
}
</script>

索引.vue

<template>
    <h1>Index page</h1>
</template>

<script>
import axios from 'axios'
export default {
    mounted(){
        axios.get('http://127.0.0.1:5000/index').then((data)=>{
            console.log(data)
        }).catch((err)=>{
            console.log(err);
        })
    }
}
</script>

当我使用邮递员登录时,我得到响应successfully logged in,当我使用邮递员获取 url/index 时,我进入"user is logged in"但是response.data当我使用浏览器(chrome)从 vuejs 服务器登录时,我仍然进入"successfully logged in"response.data.msg但是当我转到 /index 时,我得到"user is not logged in".

我注意到的另一件事是,在登录请求之后的邮递员中有一个带有 cookie id 的 set-cookie 标头, Set-Cookie = session=77e40d54-066c-48a7-9b2b-88f36d9a3b86; HttpOnly; Path=/但是当我在标头字段中控制台记录来自 vuejs 的响应时,没有 set-cookie 标头(只有 application-type 和内容长度)

4

2 回答 2

1

在没有找到可行的解决方案后,我使用 JWT 解决了这个问题
文档:https ://flask-jwt-extended.readthedocs.io/en/stable/

当客户端第一次发出请求时,flask 服务器对客户端进行身份验证,如果成功通过身份验证,它会发送 jwt 令牌和响应。客户端(vuejs)在对服务器的后续请求中使用此令牌,并且每次服务器验证标头是否包含令牌

于 2021-02-18T11:23:29.090 回答
0

我认为您在 get 电话中失踪 {withCredentials: true}了,但我可能是错的。

于 2021-02-16T09:47:13.317 回答