Flutter用户认证后调用Firebase实时数据库REST API返回404错误
问题原因与修复方案
1. 令牌获取逻辑空安全错误
Auth类的token getter判断顺序错误,先访问了_expiryDate!再判断_expiryDate是否为空,会触发空异常导致返回null令牌:
原有代码:
String? get token { if(_token != null && _expiryDate!.isAfter(DateTime.now()) && _expiryDate != null) { return _token; } return null; }
调整判断顺序修复:
String? get token { if(_token != null && _expiryDate != null && _expiryDate!.isAfter(DateTime.now())) { return _token; } return null; }
2. 数据库请求URL拼接错误,额外携带错误认证头
这是触发404报错的核心原因:
使用Uri.https构造请求时,直接把查询参数?auth=$token拼到了路径参数里,Uri会自动对特殊字符做转义,导致实际请求的路径错误触发404。同时额外加了Basic类型的Authorization头,Firebase实时数据库的REST接口不支持Basic认证,两种认证方式冲突也会导致权限校验失败。
原有请求代码:
final url = Uri.https('form-app-c5343-default-rtdb.firebaseio.com', '/products.json?auth=$token'); final response = await http.get( url, headers: { HttpHeaders.authorizationHeader : "Basic $token" } );
修改后将查询参数放到Uri.https的第三个参数中,删除错误的认证头即可:
final url = Uri.https( 'form-app-c5343-default-rtdb.firebaseio.com', '/products.json', {'auth': token} // 查询参数单独传入避免转义 ); final response = await http.get(url);
如果偏向用请求头传递令牌,也可以改成Bearer类型的头,不需要在URL带参数:
final url = Uri.https('form-app-c5343-default-rtdb.firebaseio.com', '/products.json'); final response = await http.get( url, headers: { HttpHeaders.authorizationHeader : "Bearer $token" } );
3. 缺少响应状态码判断逻辑
原有逻辑拿到响应后没有先判断状态码就直接解码,请求失败时返回的非JSON内容会触发解析异常,建议增加状态码校验:
final response = await http.get(url); if (response.statusCode >= 400) { throw HttpException('请求失败,状态码:${response.statusCode}'); } final extractedData = json.decode(response.body);
内容的提问来源于stack exchange,提问作者coolhack7
相关产品推荐
相关产品推荐

