В сентябре этого года группа наших разработчиков посетила Java-конференцию SpringOne2GX, проходившую в Вашингтоне. Это одна из крупнейших подобных конференций, и мы не могли пройти мимо. Предлагаем вашему вниманию рассказ о том, что полезного и интересного мы вынесли для себя по результатам этой конференции.

Фреймворк Spring предоставляет программисту отличные средства для разработки приложений, в нем есть практически все, что может понадобиться. Более того, сегодня Spring задает вектор дальнейшего развития всей индустрии. Spring boot и микросервисы — тому пример.

В этой статье мы покажем, как просто с помощью Spring можно создать свой микросервис, использующий OAuth 2.0 и OpenID Connect для аутентификации в Google и получения информации о пользователе, дающем микросервису права на выполнение какой-то задачи от его имени. Ради упрощения, здесь будет приведен пример только с аутентификацией и просмотром информации о пользователе, а всё остальное, включая теорию по OAuth и OpenID Connect, будет опущено. Итак, начнем.

Для начала создадим проект. Проще всего использовать Spring Initializer, в нашем примере просто указано название проекта и необходимые модули. Вот и готово приложение Spring Boot c мавен-файлом, подключающим все необходимые зависимости создано автоматически.

Далее нам понадобится аннотация @EnableOAuth2Sso. Согласно документации, она позволяет создать точку аутентификации single sign on, при этом сама будет читать параметры конфигурации. Поскольку в этом примере создается web-приложение, мы расширяем стандартный WebSecurityConfigurerAdapter . Вот как он выглядит:

   @EnableOAuth2Sso
   public static class LoginConfigurer extends WebSecurityConfigurerAdapter {
       @Override
       public void configure(HttpSecurity http) throws Exception {
           http.antMatcher("/main/**").authorizeRequests().anyRequest()
             .authenticated();
       }
   }

Здесь main — это restfull root для нашего приложения, все запросы к нему должны быть аутентифицированы. Теперь займемся конфигурацией для аутентификации с помощью сервисов Google. Для этого нам понадобится создать свой secret code и связать его со своим client id у провайдера. Это можно сделать здесь: https://console.developers.google.com

Вот как выглядит окно создания своего Client ID:



Выбираем Web application, указываем название приложения и точку редиректа после успешной аутентификации, и появляется такое окно:



Там, где указаны my client ID и my client secret, вы увидите свой собственный ID и secret. Далее создаем конфигурацию:

spring:
 profiles: google
security:
 oauth2:
   client:
     clientId: my client ID.apps.googleusercontent.com
     clientSecret: my client secret
     accessTokenUri: https://accounts.google.com/o/oauth2/token
     userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
     scope: openid profile
   resource:
     jwt.keyUri:
     userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo

Обратите внимание, что в scope указано не только openid, но еще и profile — это позволит при логине указать, к чему конкретно будет даваться доступ приложению. Так как у google много различных сервисов, то мы можем давать доступ и к этим сервсам просто добавив их в конфигурацию.

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

   @RequestMapping("/user")
   public Principal user(Principal user) {
       return user;
   }

А теперь, собираем всё в кучу. Ниже приведен скриншот приложения в IDE и листинги всех файлов:



Приложение:

package com.nix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

@Configuration
@ComponentScan
@EnableAutoConfiguration
@RestController
@RequestMapping("/main")
public class SsoOpenIdConnectApplication {
   @RequestMapping("/user")
   public Principal user(Principal user) {
       return user;
   }

   public static void main(String[] args) {
       SpringApplication.run(SsoOpenIdConnectApplication.class, args);
   }

   @Component
   @EnableOAuth2Sso
   public static class LoginConfigurer extends WebSecurityConfigurerAdapter {
       @Override
       public void configure(HttpSecurity http) throws Exception {
           http.antMatcher("/main/**").authorizeRequests().anyRequest()
             .authenticated();
       }
   }
}

Конфигурация к нему (application.yml). При запуске конфигурации в Spring Boot не забудьте указать “google” в качестве активного профиля:

server:
 port: 9999

security:
 ignored: /,/favicon.ico,/index.html
 sessions: ALWAYS
 oauth2:
   sso:
     loginPath: /main/login

---
spring:
 profiles: google
security:
 oauth2:
   client:
     clientId: my client ID.apps.googleusercontent.com
     clientSecret: my client secret
     accessTokenUri: https://accounts.google.com/o/oauth2/token
     userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
     scope: openid profile
   resource:
     jwt.keyUri:
     userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo

Ну и index.html:

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script>
        $(document).ready(function() {
            $("#userInfo").click(function(){
                $.get("main/user", function(data, status) {
                    if (status === "success") {
                        $("#userData").text(JSON.stringify(data, null, '\t'));
                    }
                });
            });
        });
    </script>
</head>
<body>
    <div>
        <a href='main/login' id="login">login</a>
        <button id="userInfo">User info</button>
        <pre id="userData"></pre>
    </div>
</body>
</html>


Вот так будет выглядеть аутентификация вашего приложения при запуске:



В результате всех вышеописанных действий, мы получили способное работать в облаке приложение с single sign on, использующее Google в качестве провайдера для OpenID Connect. При желании можно создать множество других микросервисов, аналогично настроенных и использующих тот же single sign on. Тот факт, что вся настройка на Google лежит в конфигурациях, позволяет очень быстро переключиться на другого провайдера. И несмотря на кажущуюся сложность настройки SSO, данное решение является столь же простым, как и basic authentication.

Комментарии (0)