使用ngrok暴露本地Flask后端时,Axios跨域请求因CORS凭证兼容问题报错的求助
使用ngrok暴露本地Flask后端时,Axios跨域请求因CORS凭证兼容问题报错的求助
问题描述
我最近碰到一个跨域请求的棘手问题,想请大家帮忙看看:
- 我的Flask后端跑在
http://localhost:5000,React前端部署在http://localhost:3000,直接用本地后端地址的时候,所有请求都能正常工作。 - 因为需要从其他网络访问本地后端,我用ngrok生成了一个公网地址(比如
https://453c-162-199-93-254.ngrok-free.app),但用这个地址通过Axios发起请求时,浏览器直接抛出了CORS错误:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ‘https://453c-162-199-93-254.ngrok-free.app/@me’. (Reason: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’)
另外,用ngrok地址访问时还会返回user: Unauthorized,哪怕绕开了ngrok的浏览器警告,登录后的GET /@me请求依然无法正常获取数据。
已尝试的解决方案
我已经试了好几种方法,但都没能彻底解决问题:
- 放弃自定义的axios实例(之前用
axios.create创建了httpClient),直接用axios.get发起请求 - 在创建axios实例前设置全局的
axios.defaults.withCredentials = true,也在单个请求里单独加了withCredentials: true选项:const resp = await axios.get(`${backendLink}/@me`, { withCredentials: true }); - 在Flask里配置CORS时指定origins:
CORS(app, origins=["http://localhost:3000"]),也试过给接口单独加@cross_origin(origins=[...])装饰器 - 在React的
package.json里配置了代理:"proxy": "https://fe10-162-199-93-254.ngrok-free.app" - 给Flask的session配置了SameSite和Secure属性:
app.config["SESSION_COOKIE_SAMESITE"] = "None" app.config["SESSION_COOKIE_SECURE"] = True
最终解决方法
后来我调整了Flask的CORS配置,把ngrok的公网地址也加入到origins列表里,同时开启supports_credentials=True,问题居然就解决了!具体配置代码如下:
CORS(app, supports_credentials=True, origins=[ "http://localhost:3000", "http://thecasecomp.com", # 我的线上域名,大家根据自己的实际情况替换 "https://453c-162-199-93-254.ngrok-free.app" # ngrok生成的公网地址 ])
现在想明白了,当请求携带凭证(比如session cookie)时,浏览器是不允许Access-Control-Allow-Origin设为通配符*的,必须把前端所在的所有域名(包括本地开发地址和ngrok公网地址)都明确加入到CORS的origins中才行。
我的Flask后端核心代码
给大家贴一下我的app.py核心部分,方便参考:
from flask import Flask, request, abort, jsonify, session from flask_bcrypt import Bcrypt from flask_session import Session from flask_cors import CORS, cross_origin from config import ApplicationConfig from models import db, User app = Flask(__name__) app.config.from_object(ApplicationConfig) bcrypt = Bcrypt(app) # 关键的CORS配置 CORS(app, supports_credentials=True, origins=[ "http://localhost:3000", "http://localhost:5000", "https://453c-162-199-93-254.ngrok-free.app", ]) server_session = Session(app) db.init_app(app) with app.app_context(): db.create_all() # 获取当前登录用户接口 @app.route("/@me") def get_current_user(): user_id = session.get("user_id") if not user_id: return jsonify({"error": "User unauthorized."}), 401 user = User.query.filter_by(id = user_id).first() if user is None: return jsonify({"error": "User not found."}), 404 return jsonify({ "id": user.id, "email": user.email, "first_name": user.first_name, "last_name": user.last_name, "phone_number": user.phone_number, "grade": user.grade, "school": user.school }) # 注册接口(省略部分代码) @app.route("/registration", methods=["POST"]) def register_user(): email = request.json["email"] password = request.json["password"] first_name = request.json["firstName"] last_name = request.json["lastName"] phone_number = request.json["phone"] grade = request.json["grade"] school = request.json["school"] user_exists = User.query.filter_by(email = email).first() is not None if user_exists: return jsonify({"error": "User already exists."}), 409 hashed_password = bcrypt.generate_password_hash(password) new_user = User(email = email, password = hashed_password, first_name = first_name, last_name = last_name, phone_number = phone_number, grade = grade, school = school) db.session.add(new_user) db.session.commit() session["user_id"] = new_user.id return jsonify({ "id": new_user.id, "email": new_user.email, "first_name": new_user.first_name, "last_name": new_user.last_name, "phone_number": new_user.phone_number, "grade": new_user.grade, "school": new_user.school }) # 删除用户接口(省略部分代码) @app.route("/remove-user", methods=["POST"]) def remove_user(): user_id = request.json["user_id"] if not user_id: return jsonify({"error": "User ID not found."}), 404 user = User.query.filter_by(id=user_id).first() if user: db.session.delete(user) db.session.commit() return jsonify({"message": "User removed successfully."}), 200
内容来源于stack exchange
相关产品推荐
相关产品推荐

