#java #javafx #google-api #google-oauth
#java #javafx #google-api #google-oauth
Вопрос:
Я пишу приложение JavaFX, и у меня есть кнопка входа, чтобы получить учетные данные. При нажатии кнопки контроллер запускает аутентификацию Google, этот фрагмент кода открывает браузер, если StoredCredential отсутствует:
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport
, JSON_FACTORY
,clientSecrets
, scope)
.setAccessType("offline")
.setDataStoreFactory(dataStoreFactory)
.setApprovalPrompt("auto")
.build();
LocalServerReceiver serverReceiver = new LocalServerReceiver.Builder().setPort(8888).build();
credentials = new AuthorizationCodeInstalledApp(flow, serverReceiver).authorize("user");
Во время выполнения этого кода поток приложения ожидает, поэтому приложение безответственно. Я попытался закрыть браузер, чтобы посмотреть, что произойдет в этом случае, приложение по-прежнему безответственно.
Как я мог это решить? Должен ли я запускать код авторизации в отдельном потоке и продолжать, только если учетные данные действительны?
Комментарии:
1. docs.oracle.com/javase/8/javafx/interoperability-tutorial/…
Ответ №1:
Итак, проведя некоторые исследования, я обнаружил, что об этой проблеме сообщалось два года назад в репозитории «Клиентская библиотека Google OAuth для Java» на GitHub, здесь # 175 и здесь # 182. Как и предлагалось, я попытался использовать JavaFX WebView, но у него также есть некоторые проблемы, вероятно, потому, что он немного устарел. Я смог получить учетные данные, но не смог получить «Полученный код подтверждения. Теперь вы можете закрыть страницу «это окно».
Есть несколько альтернатив WebView, таких как JxBrowser или JCEF, однако первый из них безумно дорогой, а последний нелегко реализовать в JavaFX.
В итоге я использовал установленный браузер и запустил поток аутентификации в отдельном потоке. Кнопка входа в систему отключена на 90 секунд, и начинается анимация обратного отсчета с использованием временной шкалы JavaFX. Каждую секунду он проверяет, действительны ли учетные данные. Через 90 секунд временная шкала останавливается, и если учетные данные все еще недействительны, она проверяет, все ли еще выполняется поток, и останавливает его.
Вот код:
GoogleAuthentication authentication = new GoogleAuthentication();
Task<Void> oauthTask = new Task<>() {
@Override
protected Void call() throws Exception {
authentication.init();
return null;
}
};
Thread oauthThread = new Thread(oauthTask);
oauthThread.setDaemon(true);
AtomicInteger waitTime = new AtomicInteger(90);
loginButton.setDisable(true);
loginButton.setText(waitTime "s");
Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.getKeyFrames().add(
new KeyFrame(Duration.seconds(1), event -> {
if (isValidCredentials(authentication.getCredentials())) {
resetButton(timeline);
System.out.println(authentication.getCredentialsExpiration());
return;
}
waitTime.getAndDecrement();
loginButton.setText(waitTime "s");
if (waitTime.intValue() <= 0) {
oauthThread.stop();
resetButton(timeline);
}
})
);
timeline.play();
oauthThread.start();
Да, я знаю, что мне не следует использовать метод Thread.stop(), я знаю, что он устарел, но это единственный способ заставить его работать, в противном случае LocalServerReceiver, используемый для аутентификации, выдает это исключение «java.net.BindException: Адрес уже используется: bind».
Я пробовал с помощью interrupt(), но поток просто продолжает ждать, спасибо Google за вашу … «не очень хорошую» реализацию, я думаю.
Лучшее решение — сохранить LocalServerReceiver в качестве переменной экземпляра, использовать getter и использовать метод stop().
Таким образом, это oauthThread.stop();
становится authentication.getServerReceiver().stop();
окруженным исключением try catch IOException
Пока это мое решение, я должен признать, что я впервые работаю с потоками и параллелизмом по-настоящему. Если у вас есть какие-либо другие идеи или улучшения, пожалуйста, прокомментируйте.
Ответ №2:
Взгляните сюда:https://docs.oracle.com/javafx/2/webview/jfxpub-webview.htm
Документы по использованию всплывающих окон и взаимодействию с ними