Я много искал, но, кажется, невозможно найти решение от начала до конца по этой теме. Исходя из этого, я уже реализовал регистрацию в Cognito, вход в систему и обновление учетных данных в двух собственных приложениях для iOS и Android, поэтому я разработал (по крайней мере) базовое понимание процесса аутентификации.
Эти мобильные приложения используют простейшую настройку Cognito: пул пользователей, пул удостоверений с ролью IAM для аутентифицированных пользователей и использование без аутентификации невозможно. Я не использую (по крайней мере пока) логин Facebook, Google или Amazon, а также другие способы аутентификации.
Теперь мне нужно сделать настольную версию этих приложений на Java, и мне кажется, что это совершенно другой зверь. Что я хотел бы сделать, это:
- Откройте окно входа в приложение на рабочем столе Java;
- Введите имя пользователя и пароль в их поля и нажмите кнопку входа;
- Получение некоторых учетных данных и начало использования приложения, подключающегося к другим сервисам AWS, особенно мне нужно использовать S3, Lambda и DynamoDB.
Способ достижения этого на бумаге достаточно прост:
- Получить токен из пула пользователей Cognito;
- Передать этот токен в пул идентификации Cognito в обмен на некоторые учетные данные;
- Используйте эти учетные данные для доступа к другим сервисам AWS.
После прочтения большого количества документации, загрузки множества примеров различных проектов и большого отчаяния я в конце концов нашел способ реализовать это в мобильных приложениях. Например, в Android поток аутентификации работает так:
- Создание CognitoUserPool с использованием UserPoolID, AppClientID, PoolRegion и (необязательно) ClientSecret;
- Создание поставщика учетных данных с использованием IdentityPoolID и PoolRegion;
- В пользовательском интерфейсе приложения введите имя пользователя и пароль и нажмите кнопку входа в систему;
- Извлечение CognitoUser с использованием этого имени пользователя из ранее созданного UserPool;
- Получить CognitoUserSession для этого CognitoUser, используя AuthenticationHandler с различными обратными вызовами для передачи пароля при необходимости;
- Добавьте этот CognitoUserSession к провайдеру учетных данных, созданному ранее, в форме TokenKey + токен JWT, извлеченный из сеанса.
- На этом этапе, когда мне нужно получить доступ к S3, Lambda или DynamoDB, я просто передаю этот поставщик учетных данных в качестве параметра для своих конструкторов клиентов.
Реализовать ту же функциональность с помощью Java SDK мне кажется намного сложнее.
Мне удалось довольно легко реализовать регистрацию пользователей. Однако с пользователями Вход в систему, я не знаю, с чего начать.
Каждый пример делает это по-своему. Кроме того, в каждом примере используются особые варианты использования, такие как авторизованные разработчиком входы в систему или пользовательские URL-адреса для подключения к некоторому собственному бэкэнду. Почему так сложно найти пример для базового варианта использования, который мне нужен? Я начинаю думать, что мой базовый вариант использования вовсе не базовый, а скорее нетипичный Почему вход в систему с именем пользователя и паролем к службе пользователей / учетных данных по умолчанию для AWS будет нетипичным, однако я действительно не знаю.
Лучшее, что я сделал до сих пор, - это копирование соответствующих классов из этого примера проекта (из которого я также взял часть регистрации, которая работает довольно хорошо) и получение печати IdToken, AccessToken и RefreshToken в консоли. Они напечатаны правильно и не являются нулевыми.
На самом деле я не могу понять, как получить учетные данные и добавить их к поставщику учетных данных, чтобы создать экземпляры клиентов для доступа к другим службам AWS. Единственный способ, который я вижу в проекте, - это вызвать метод
Credentials getCredentials(String accessCode)
, который, как я полагаю, должен принимать код доступа, полученный методом InitAuth (который запускает поток аутентификации OAuth2.0, пожалуйста, исправьте меня, если я ошибаюсь). Проблема в том, что я не могу найти способ получить этот код. Я не могу найти онлайн пример кода доступа, чтобы увидеть, как он выглядит. Я попытался поставить один из токенов, и веб-запрос отвечает
{"error":"invalid_grant"}
, который указывает на то, что он не является действительным кодом, но по крайней мере веб-запрос действителен.
Чтобы было понятнее, я могу сделать следующее:
String username; //retrieved from UI
String password; //retrieved from UI
//I copied AuthenticationHelper as is from the project
AuthenticationHelper helper = new AuthenticationHelper(POOL_ID, CLIENT_APP_ID, CLIENT_SECRET);
//I then retrieve the tokens with SRP authentication
AuthenticationResultType result = helper.performSRPAuthentication(username, password);
//Now I can successfully print the tokens, for example:
System.out.println(result.getAccessToken());
Как я могу получить учетные данные отсюда? Где я должен поместить идентификатор пула идентификаторов? В Android я просто добавляю токен JWT к HashMap
и использую его как
credentialsProvider.setLogins(loginsMap)
.
Кроме того, этот проект содержит классы с сотнями строк кода, переменными BigInteger, жестко запрограммированными строками из многих строк случайных символов (какой-то ключ или токен, я полагаю) и другой черной магии в этом роде (особенно в классе AuthenticationHelper) , Еще одна вещь, которая мне не нравится в этом решении, заключается в том, что оно получает учетные данные посредством написанных вручную веб-запросов (с помощью другого отдельного класса, созданного специально для выполнения запроса). Неужели нет в Java SDK какого-либо удобного метода, который оборачивает все эти вещи в кучу элегантных строк кода? Зачем называть это SDK, чем? SDK для iOS и Android обрабатывают все это в более простой форме. Это связано с тем, что они ожидают, что разработчик настольного приложения будет более способным / опытным, в отличие от обычного парня, который однажды, вставая с постели, решает сделать приложение для iOS / Android [alludes себе] ? Это объясняет их стремление сделать мобильные SDK более удобными для разработчиков.
Во-первых, мне очень трудно поверить, что я должен это делать, читая, кто знает что на странице документа, кто знает, где, чтобы войти в систему, что заставляет меня думать, что я действительно что-то упускаю. Я буквально прочитал каждый вопрос о стеке и документацию, которую смог найти Дело в том, что почти всегда есть страница документации AWS для того, что мне нужно, но иногда ее найти не так просто, по крайней мере для документации Cognito.
Я прочитал, что могу поместить файл с необходимыми учетными данными в файловую систему ПК, и Java SDK будет использовать эти учетные данные для доступа ко всем ресурсам, однако, насколько я понимаю, этот метод зарезервирован для приложений Java, работающих на сервере как серверная часть (сервлеты), где конечный пользователь не может получить к ним доступ через свой браузер. Мое приложение является настольным приложением для конечных пользователей, поэтому я даже не могу оставить учетные данные AWS на ПК пользователя (исправьте меня, если я ошибаюсь, я бы очень хотел сделать что-то настолько простое).
Что меня действительно пугает, так это то, что вход в систему с пулом пользователей и пулом идентификации может быть невозможен вообще. Я знаю, что материал, связанный с Cognito, был добавлен в Java SDK гораздо позже, он был доступен для iOS, Android и JavaScript. Но если они добавят его, я полагаю, что он должен поддерживать поток аутентификации, по крайней мере, аналогичный таковому для мобильных аналогов.
Что еще больше усугубляет проблему, так это то, что я изначально заставил все функции моего приложения работать в автономном режиме. Я думал, что в конечном итоге я бы интегрировал AWS в приложение. Таким образом, приложение становится немного более модульным, а связанные с AWS вещи сосредоточены в пакете, отделенном от остальной логики приложения и пользовательского интерфейса. В моем море невежества это кажется мне хорошей практикой, но теперь, если мне не удается решить эту проблему, я бросаю месяцы работы в мусорное ведро, только чтобы понять, что мне нужно создать веб-приложение, потому что JavaScript гораздо больше поддерживается.
Даже на MobileHub единственными вариантами создания ClientApp на Cognito являются iOS, Android, JavaScript и React-что-то.
Когда предоставляется документация или примеры для других языков / SDK, Java часто опускается, и наиболее часто встречающийся вариант - .NET.Чтобы сделать мое разочарование еще больше, каждый раз, когда я что-то ищу в поисковой системе, тот факт, что слово «Java» содержится в слове «JavaScript», запутывает некоторые результаты, которые могут быть полезны, потому что все вещи, связанные с SDK JavaScript, как правило, более высокий рейтинг в поисковых системах, чем в Java (это может частично объяснить, почему вещи, связанные с .NET, проще найти, по крайней мере, на StackOverflow или других сайтах вопросов и ответов).
В заключение, все это создало некоторые вопросы в моей голове:
Почему так мало людей нуждаются в этом способе аутентификации (с именем пользователя и паролем)? Мне кажется, это довольно распространенный и разумный вариант использования для настольного приложения. Я знаю, что рост веб-приложений зашкаливает, но, учитывая, что сегодня Java является одним из наиболее часто используемых языков, как получается, что никому не нужно делать простой вход из настольного приложения? Что приводит к следующему вопросу:
Есть ли что-то изначально плохое / неправильное / рискованное / глупое в использовании Java SDK для настольного приложения? Предназначено ли оно только для использования на сервере в качестве бэкэнда или для веб-приложения? Каким должно быть решение, чтобы создать настольное приложение, которое подключается к сервисам AWS? Это неправильно делать подключенное к AWS настольное приложение вообще? Должно ли веб-приложение быть единственным вариантом для рассмотрения? Зачем? Я выбрал Java для реализации приложения, которое будет работать на вдовах, macOS и Linux. Я также выбрал Java, потому что я думал, что он будет в основном похож на Android SDK в своем использовании, учитывая, что его код должен быть независимым от пользовательского интерфейса платформы, что упрощает повторное использование кода. Я был не прав.
Если нет ничего плохого в использовании Java SDK, как это, возможно, некоторые
хорошая душа, пожалуйста, помогите мне найти пример, который идет от положить
имя пользователя и пароль в двух полях, а также создать экземпляр клиента для
получить доступ к другим сервисам AWS (таким как клиент S3) на рабочем столе Java
приложение?
Скажите мне все, что вам нужно знать, и я отредактирую вопрос.
Пожалуйста, кто-нибудь, помогите мне, я схожу с ума.