У меня есть приложение Flutter, которое использует Карты Google для отображения карт и выполнения вызовов API-интерфейса Places для поиска ближайших магазинов на основе местоположения пользователя. Во время разработки я не ограничивал ключи API, но теперь, когда я хочу перейти к производству, я ограничил ключи как для Android, так и для iOS.
Вот как я вызываю Places API:
final String apiUrl =
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${cords.latitude}%2C${cords.longitude}&radius=$radius&type=$type&key=$apiKey";
final response = await http.get(Uri.parse(apiUrl));
Я пытался ограничить ключи API для iOS и Android (по одному ключу для каждого приложения). Карта отображается правильно, но вызовы API мест возвращают следующую ошибку:
{
"error_message" : "This IP, site or mobile application is not authorized to use this API key. Request received from IP address x.x.x.x, with empty referer",
"html_attributions" : [],
"results" : [],
"status" : "REQUEST_DENIED"
}
После довольно долгого поиска я нашел сообщение о переполнении стека, в котором говорилось, что некоторые API-интерфейсы карт Google предназначены для вызова из внутренней системы, а не непосредственно из внешнего интерфейса. Вот ссылка на пост для справки: Android Google Maps Direction Api — ограничение ключа API не работает
Это заставило меня задуматься, возможно, то же самое произойдет и со мной. Судя по предоставленной пользователем ссылке, оказывается, что это действительно так... (Пожалуйста, дайте мне знать, если я ошибаюсь)
Какие ключи или учетные данные следует использовать для разных продуктов Карт?
Я подумываю изменить способ вызова API Places. Поскольку я уже использую Firebase, я подумываю о запуске облачной функции для вызова API-интерфейса Places, а затем о пересылке ответа JSON на клиентский телефон. Однако я не уверен, следует ли мне ограничивать ключ API для облачной функции.
Мои вопросы:
Если вы считаете, что я могу решить эту проблему другим способом, дайте мне знать. Я также заметил в таблице записи для Places SDK для Android и iOS, которые можно ограничить приложением, но я не знаю, подходит ли это для моего случая. потому что я использую флаттер.
Что следует уточнить:
Любые предложения или идеи будут с благодарностью приняты. Заранее спасибо.
Да, 1 ключ API для Android, он предназначен для SDK карт Android, а затем для вызовов API мест и еще один для ios.
Спасибо за разъяснение! В этом случае я бы посоветовал вам использовать отдельные ключи API также для запроса Places API и для загрузки карт. Вам не следует беспокоиться о наличии нескольких ключей API (максимум 300 ключей), поскольку это на самом деле считается хорошей практикой, поскольку вы можете отслеживать каждый ключ API в консоли. Также обратите внимание, что ограничение приложений для iOS и Android не позволит ключу API получать запросы к веб-службам. Таким образом, выполнение запроса веб-сервисов на стороне сервера является правильным.
Веб-сервисы (в данном случае API-интерфейс Places) можно использовать только с ключами API с ограничением по IP-адресу. Затем вы можете использовать прокси-сервер для запроса веб-сервисов, чтобы еще больше его защитить: Developers.google.com/maps/…
Если вы не можете получить уникальный IP-адрес в облачной функции, по крайней мере, ваш код будет работать в среде, в которой злоумышленники не смогут скомпрометировать ваш ключ API. Тем не менее, я бы, по крайней мере, ограничил использование ключа конкретными API-интерфейсами (в случае, если в проекте включены другие), а затем не использовал бы тот же ключ где-либо еще.





В конечном итоге я использовал вызываемую облачную функцию, поскольку я уже использовал Firebase и реализовал проверку приложений, чтобы убедиться, что только мои приложения могут запускать эту функцию, а также для обеспечения безопасности ключа API я использовал диспетчер секретных служб Google Cloud.
Это также хорошая практика, и предлагается ограничить ее конкретными API, которые вы хотите использовать.
Для всех, кто интересуется защитой конфиденциальной информации, Cloud Functions for Firebase интегрируется с Google Cloud Secret Manager.
https://firebase.google.com/docs/functions/config-env?gen=2nd#create-secret
export const fetchFromGoogleMaps = functions.onCall({
secrets: ["secret_name"],
enforceAppCheck: true,
}, async (request) => {
const apiKey = process.env.secret_name;
const apiUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&type=${type}&key=${apiKey}`;
return await axios.default.get(apiUrl).then((apiResponse) => {
// ...
}).catch((error) => {
// handle the error
});
Просто чтобы убедиться, что я правильно понимаю, используете ли вы один и тот же ключ API для загрузки карты и запроса к Places API для каждой платформы?