Flutter Web无法识别Dart后端CORS配置,求助解决方案
问题分析与解决方案
核心问题排查
- Origin不匹配:你设置的
Access-Control-Allow-Origin为https://localhost,但Flutter Web默认运行在http://localhost:<端口>,协议或端口不匹配会直接触发CORS拦截。 - OPTIONS请求未动态适配:前端发送的OPTIONS预检请求会携带
Access-Control-Request-Headers,固定返回允许头的方式无法匹配前端实际发送的自定义头,导致浏览器拒绝后续请求。 - 中间件顺序逻辑:当前CORS中间件在
contentTypeJson之后执行,可能导致部分响应头覆盖或未正确合并。
修正后的CORS中间件实现
import 'package:shelf/shelf.dart'; class MiddlewareInterception { static Middleware get contentTypeJson => createMiddleware( responseHandler: (Response res) => res.change( headers: { 'content-type': 'application/json', 'xpto': '123', }, ), ); static Middleware get cors { return createMiddleware( requestHandler: (Request req) { // 处理OPTIONS预检请求 if (req.method == 'OPTIONS') { // 动态获取前端请求的Origin final origin = req.headers['origin'] ?? '*'; // 匹配前端发送的自定义请求头 final requestHeaders = req.headers['access-control-request-headers'] ?? ''; final corsHeaders = { 'Access-Control-Allow-Origin': origin, 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': requestHeaders.isNotEmpty ? requestHeaders : 'Origin, Content-Type, Accept, Authorization, X-Requested-With', 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Max-Age': '86400', }; return Response(200, headers: corsHeaders); } return null; }, responseHandler: (Response res) { // 给所有业务响应添加CORS头 final origin = res.request?.headers['origin'] ?? '*'; return res.change(headers: { 'Access-Control-Allow-Origin': origin, 'Access-Control-Allow-Credentials': 'true', }); }, ); } }
调整中间件执行顺序
将CORS中间件移至contentTypeJson之前,确保所有请求先经过CORS校验:
final handler = Pipeline() .addMiddleware(logRequests()) .addMiddleware(MiddlewareInterception.cors) .addMiddleware(MiddlewareInterception.contentTypeJson) .addHandler(cascadeHandler);
前端Flutter Web请求配置
若后端启用了Access-Control-Allow-Credentials: true,前端请求必须同步开启withCredentials:
import 'package:http/http.dart' as http; import 'dart:convert'; final response = await http.post( Uri.parse('http://your-backend-ip:8080/api'), body: jsonEncode({'key': 'value'}), headers: {'Content-Type': 'application/json'}, withCredentials: true, // 必须添加该参数 );
额外验证步骤
- 打开浏览器开发者工具的网络面板,查看OPTIONS请求的响应头是否包含正确的
Access-Control-Allow-Origin和允许的请求头。 - 确认后端服务绑定的IP为
0.0.0.0(而非127.0.0.1),确保前端能正常访问。
内容的提问来源于stack exchange,提问作者GTorraski
相关产品推荐
相关产品推荐

