Java google oauth2 example

OAuth 2.0 и клиентская библиотека Google OAuth для Java

Оптимизируйте свои подборки Сохраняйте и классифицируйте контент в соответствии со своими настройками.

Обзор

Цель: в этом документе описываются общие функции OAuth 2.0, предлагаемые клиентской библиотекой Google OAuth для Java. Вы можете использовать эти функции для аутентификации и авторизации для любых интернет-сервисов.

Инструкции по использованию GoogleCredential для авторизации OAuth 2.0 в службах Google см. в разделе Использование OAuth 2.0 с клиентской библиотекой API Google для Java .

Описание: OAuth 2.0 — это стандартная спецификация, позволяющая конечным пользователям безопасно авторизовать клиентское приложение для доступа к защищенным ресурсам на стороне сервера. Кроме того, спецификация токена-носителя OAuth 2.0 объясняет, как получить доступ к этим защищенным ресурсам с помощью токена доступа, предоставленного в процессе авторизации конечного пользователя.

Дополнительные сведения см. в документации по Javadoc для следующих пакетов:

Регистрация клиента

Прежде чем использовать клиентскую библиотеку Google OAuth для Java, вам, вероятно, потребуется зарегистрировать свое приложение на сервере авторизации, чтобы получить идентификатор клиента и секрет клиента. (Общие сведения об этом процессе см. в спецификации регистрации клиентов .)

Учетные данные и хранилище учетных данных

Credential — это потокобезопасный вспомогательный класс OAuth 2.0 для доступа к защищенным ресурсам с использованием токена доступа. При использовании токена обновления Credential также обновляет токен доступа по истечении срока действия токена доступа с использованием токена обновления. Например, если у вас уже есть токен доступа, вы можете сделать запрос следующим образом:

public static HttpResponse executeGet( HttpTransport transport, JsonFactory jsonFactory, String accessToken, GenericUrl url) throws IOException

Большинству приложений необходимо сохранять токен доступа к учетным данным и токен обновления, чтобы в будущем избежать перенаправления на страницу авторизации в браузере. Реализация CredentialStore в этой библиотеке устарела и будет удалена в будущих выпусках. Альтернативой является использование интерфейсов DataStoreFactory и DataStore с StoredCredential , которые предоставляются клиентской библиотекой Google HTTP для Java .

Вы можете использовать одну из следующих реализаций, предоставляемых библиотекой:

  • JdoDataStoreFactory сохраняет учетные данные с помощью JDO.
  • AppEngineDataStoreFactory сохраняет учетные данные с помощью API хранилища данных Google App Engine.
  • MemoryDataStoreFactory «сохраняет» учетные данные в памяти, которая полезна только в качестве краткосрочного хранилища на время жизни процесса.
  • FileDataStoreFactory сохраняет учетные данные в файле.

Пользователи Google App Engine:

Мы рекомендуем использовать AppEngineDataStoreFactory с StoredCredential . Если у вас есть учетные данные, хранящиеся по-старому, вы можете использовать для переноса добавленные вспомогательные методы migrateTo(AppEngineDataStoreFactory) или migrateTo(DataStore) .

Читайте также:  line-height

Поток кода авторизации

Используйте поток кода авторизации, чтобы позволить конечному пользователю предоставить вашему приложению доступ к своим защищенным данным. Протокол для этого потока указан в спецификации предоставления кода авторизации .

Этот поток реализуется с помощью AuthorizationCodeFlow . Шаги:

  • Конечный пользователь входит в ваше приложение. Вам необходимо связать этого пользователя с идентификатором пользователя, уникальным для вашего приложения.
  • Вызовите AuthorizationCodeFlow.loadCredential(String) на основе идентификатора пользователя, чтобы проверить, известны ли учетные данные пользователя. Если да, то все готово.
  • Если нет, вызовите AuthorizationCodeFlow.newAuthorizationUrl() и направьте браузер конечного пользователя на страницу авторизации, где он может предоставить вашему приложению доступ к своим защищенным данным.
  • Затем веб-браузер перенаправляется на URL-адрес перенаправления с параметром запроса «код», который затем можно использовать для запроса токена доступа с помощью AuthorizationCodeFlow.newTokenRequest(String) .
  • Используйте AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String) для сохранения и получения учетных данных для доступа к защищенным ресурсам.

В качестве альтернативы, если вы не используете AuthorizationCodeFlow , вы можете использовать классы более низкого уровня:

  • Используйте DataStore.get(String) для загрузки учетных данных из хранилища на основе идентификатора пользователя.
  • Используйте AuthorizationCodeRequestUrl , чтобы направить браузер на страницу авторизации.
  • Используйте AuthorizationCodeResponseUrl для обработки ответа авторизации и анализа кода авторизации.
  • Используйте AuthorizationCodeTokenRequest , чтобы запросить маркер доступа и, возможно, маркер обновления.
  • Создайте новый Credential и сохраните его с помощью DataStore.set(String, V) .
  • Получите доступ к защищенным ресурсам, используя Credential . Маркеры доступа с истекшим сроком действия автоматически обновляются с помощью маркера обновления, если это применимо. Обязательно используйте DataStoreCredentialRefreshListener и установите его для учетных данных с помощью Credential.Builder.addRefreshListener(CredentialRefreshListener) .

Поток кода авторизации сервлета

Эта библиотека предоставляет вспомогательные классы сервлетов, чтобы значительно упростить поток кода авторизации для основных случаев использования. Вы просто предоставляете конкретные подклассы AbstractAuthorizationCodeServlet и AbstractAuthorizationCodeCallbackServlet (из google-oauth-client-servlet ) и добавляете их в свой файл web.xml. Обратите внимание, что вам по-прежнему необходимо позаботиться о входе пользователя в веб-приложение и извлечь идентификатор пользователя.

public class ServletSample extends AbstractAuthorizationCodeServlet < @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException < // do stuff >@Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException < GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath("/oauth2callback"); return url.build(); >@Override protected AuthorizationCodeFlow initializeFlow() throws IOException < return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new NetHttpTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialDataStore( StoredCredential.getDefaultDataStore( new FileDataStoreFactory(new File("datastoredir")))) .build(); >@Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException < // return user ID >> public class ServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet < @Override protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential) throws ServletException, IOException < resp.sendRedirect("/"); >@Override protected void onError( HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse) throws ServletException, IOException < // handle error >@Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException < GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath("/oauth2callback"); return url.build(); >@Override protected AuthorizationCodeFlow initializeFlow() throws IOException < return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new NetHttpTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialDataStore( StoredCredential.getDefaultDataStore( new FileDataStoreFactory(new File("datastoredir")))) .build(); >@Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException < // return user ID >>

Поток кода авторизации Google App Engine

Поток кода авторизации в App Engine почти идентичен потоку кода авторизации сервлета, за исключением того, что мы можем использовать Users Java API Google App Engine. Пользователь должен войти в систему, чтобы Users Java API был включен; сведения о перенаправлении пользователей на страницу входа, если они еще не вошли в систему, см. в разделе Безопасность и проверка подлинности (в web.xml).

Читайте также:  Java stream generate sequence

Основное отличие от случая с сервлетом заключается в том, что вы предоставляете конкретные подклассы AbstractAppEngineAuthorizationCodeServlet и AbstractAppEngineAuthorizationCodeCallbackServlet (из google-oauth-client-appengine ). Они расширяют абстрактные классы сервлетов и реализуют для вас метод getUserId с помощью Users Java API. AppEngineDataStoreFactory (из клиентской библиотеки Google HTTP для Java — хороший вариант для сохранения учетных данных с помощью API хранилища данных Google App Engine.

public class AppEngineSample extends AbstractAppEngineAuthorizationCodeServlet < @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException < // do stuff >@Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException < GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath("/oauth2callback"); return url.build(); >@Override protected AuthorizationCodeFlow initializeFlow() throws IOException < return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new UrlFetchTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialStore( StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance())) .build(); >> public class AppEngineCallbackSample extends AbstractAppEngineAuthorizationCodeCallbackServlet < @Override protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential) throws ServletException, IOException < resp.sendRedirect("/"); >@Override protected void onError( HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse) throws ServletException, IOException < // handle error >@Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException < GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath("/oauth2callback"); return url.build(); >@Override protected AuthorizationCodeFlow initializeFlow() throws IOException < return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new UrlFetchTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialStore( StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance())) .build(); >>

Поток кода авторизации командной строки

Упрощенный пример кода, взятый из dailymotion-cmdline-sample :

/** Authorizes the installed application to access user's protected data. */ private static Credential authorize() throws Exception < OAuth2ClientCredentials.errorIfNotSpecified(); // set up authorization code flow AuthorizationCodeFlow flow = new AuthorizationCodeFlow.Builder(BearerToken .authorizationHeaderAccessMethod(), HTTP_TRANSPORT, JSON_FACTORY, new GenericUrl(TOKEN_SERVER_URL), new ClientParametersAuthentication( OAuth2ClientCredentials.API_KEY, OAuth2ClientCredentials.API_SECRET), OAuth2ClientCredentials.API_KEY, AUTHORIZATION_SERVER_URL).setScopes(Arrays.asList(SCOPE)) .setDataStoreFactory(DATA_STORE_FACTORY).build(); // authorize LocalServerReceiver receiver = new LocalServerReceiver.Builder().setHost( OAuth2ClientCredentials.DOMAIN).setPort(OAuth2ClientCredentials.PORT).build(); return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); >private static void run(HttpRequestFactory requestFactory) throws IOException < DailyMotionUrl url = new DailyMotionUrl("https://api.dailymotion.com/videos/favorites"); url.setFields("id,tags,title,url"); HttpRequest request = requestFactory.buildGetRequest(url); VideoFeed videoFeed = request.execute().parseAs(VideoFeed.class); . >public static void main(String[] args) < . DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR); final Credential credential = authorize(); HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() < @Override public void initialize(HttpRequest request) throws IOException < credential.initialize(request); request.setParser(new JsonObjectParser(JSON_FACTORY)); >>); run(requestFactory); . >

Клиентский поток на основе браузера

Это типичные шаги клиентского потока на основе браузера, указанные в спецификации неявного предоставления:

  • С помощью BrowserClientRequestUrl перенаправьте браузер конечного пользователя на страницу авторизации, где конечный пользователь может предоставить вашему приложению доступ к своим защищенным данным.
  • Используйте приложение JavaScript для обработки маркера доступа, найденного во фрагменте URL-адреса в URI перенаправления, который зарегистрирован на сервере авторизации.
Читайте также:  Javascript iframe createelement script

Пример использования для веб-приложения:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException < String url = new BrowserClientRequestUrl( "https://server.example.com/authorize", "s6BhdRkqt3").setState("xyz") .setRedirectUri("https://client.example.com/cb").build(); response.sendRedirect(url); >

Обнаружение просроченного токена доступа

Согласно спецификации носителя OAuth 2.0 , когда сервер вызывается для доступа к защищенному ресурсу с токеном доступа с истекшим сроком действия, сервер обычно отвечает кодом состояния HTTP 401 Unauthorized , например следующим:

HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"

Тем не менее, кажется, что в спецификации есть большая гибкость. Подробности см. в документации поставщика OAuth 2.0.

Альтернативный подход — проверить параметр expires_in в ответе токена доступа . Это указывает время жизни предоставленного маркера доступа в секундах, которое обычно составляет час. Однако срок действия токена доступа может не истечь в конце этого периода, и сервер может по-прежнему разрешать доступ. Вот почему мы обычно рекомендуем дождаться кода состояния 401 Unauthorized , а не предполагать, что срок действия токена истек на основе истекшего времени. В качестве альтернативы вы можете попытаться обновить токен доступа незадолго до истечения срока его действия, и если сервер токенов недоступен, продолжайте использовать токен доступа, пока не получите 401 . Это стратегия, используемая по умолчанию в Credential .

Другой вариант — получать новый токен доступа перед каждым запросом, но для этого каждый раз требуется дополнительный HTTP-запрос к серверу токенов, поэтому, вероятно, это плохой выбор с точки зрения скорости и использования сети. В идеале храните токен доступа в безопасном постоянном хранилище, чтобы свести к минимуму запросы приложения на новые токены доступа. (Но для установленных приложений безопасное хранение — сложная проблема.)

Обратите внимание, что токен доступа может стать недействительным по причинам, отличным от истечения срока действия, например, если пользователь явно отозвал токен, поэтому убедитесь, что ваш код обработки ошибок надежен. Как только вы обнаружите, что токен больше недействителен, например, если срок его действия истек или он был отозван, вы должны удалить токен доступа из своего хранилища. Например, на Android необходимо вызвать AccountManager.invalidateAuthToken .

Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons «С указанием авторства 4.0», а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.

Последнее обновление: 2022-11-05 UTC.

Источник

Оцените статью