Почему мое приложение Flutter не может получить доступ к развернутому сервису Django в Google Cloud Run?
Я разрабатываю приложение flutter и бэкенд Django. У меня есть бэкенд с докером и двойная настройка: Локально я использую docker-compose с google cloud proxy. Для развертывания я использую DockerFile и действия на github. При локальном развертывании к сервису можно получить доступ через браузер и приложение flutter. Однако когда сервис находится на Cloud Run, доступ к нему возможен через браузер, но не через приложение Flutter. В настройках Cloud Run сервису разрешен неавторизованный доступ. В настройках Django разрешено взаимодействие без csrf:
CSRF_TRUSTED_ORIGINS = ["https://xxxxxx"]
CORS_ALLOW_ALL_ORIGINS = True
представление, которое возвращает неавторизованное, - это google login, который получает запрос на вход с Firebase idToken:
@api_view(["POST"])
@authentication_classes([])
@permission_classes([AllowAny])
@csrf_exempt
def google_login(request) -> Response:
Мой бэкенд django оставляет эти журналы в Cloud Run
:textPayload: "Unauthorized: /api/v1/google-login/"
Я реализовал JWT-аутентификацию, которую еще нужно протестировать, но она работает, когда я запускаю сервер на своей машине. Значит, что-то не так с запросом, но я не понимаю, что именно. Браузер может получить доступ к развернутой облачной службе запуска, как я уже говорил. При сканировании журналов Network я вижу, что он отправляет запрос с csrftoken и не вижу больше никаких вещей, которые мне, возможно, нужно добавить в Flutter
request.accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding:
gzip, deflate, br, zstd
accept-language:
en-GB,en-US;q=0.9,en;q=0.8
cookie:
csrftoken=xxxxxx
priority:
u=0, i
referer:
https://xxxxxxx
sec-ch-ua:
"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"
sec-ch-ua-arch:
"arm"
sec-ch-ua-bitness:
"64"
sec-ch-ua-full-version-list:
"Chromium";v="130.0.6723.117", "Google Chrome";v="130.0.6723.117", "Not?A_Brand";v="99.0.0.0"
sec-ch-ua-mobile:
?0
sec-ch-ua-model:
""
sec-ch-ua-platform:
"macOS"
sec-ch-ua-platform-version:
"15.1.0"
Код флаттера:
Страница входа
BlocListener<FirebaseAuthCubit, FirebaseAuthState>(
listener: (context, firebaseAuthState) async {
if (firebaseAuthState is FirebaseAuthSuccess) {
context
.read<UserSessionCubit>()
.googleLogin(firebaseAuthState.idToken, _deviceLocale!);
}
},
Метод кубита:
Future<void> googleLogin(String googleIdToken, String languageCode) async {
emit(UserSessionInLoading());
try {
final UserSessionModel loginResponse = await _loginApiClient.googleLogin(googleIdToken, languageCode);
emit(UserSessionSuccess(loginResponse.accessToken, loginResponse.refreshToken, loginResponse.userId, loginResponse.languageCode));
} catch (e) {
emit(UserSessionFailure(e.toString()));
}
}
Метод клиента:
Future<UserSessionModel> googleLogin(String googleIdToken, String languageCode) async {
final Uri loginRequest = debug ? Uri.http(baseUrl, '/api/v1/google-login/') : Uri.https(baseUrl, '/api/v1/google-login/');
final response = await _dioClient.post(
loginRequest.toString(),
data: jsonEncode({'googleIdToken': googleIdToken, 'languageCode': languageCode}),
options: Options(headers: {'Content-Type': 'application/json'}),
// headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
log(response.data.toString());
final jsonResponse = response.data;
return UserSessionModel.fromJson(jsonResponse);
} else {
log(response.data.toString());
throw LoginRequestFailure();
}
}
void log(String message) {
if (debug) {
print(message);
}
}