Статьи

Миграция приложений OAuth2 из Spring Boot 1.2 в 1.3

В Spring Boot 1.3 появилось несколько новых функций для клиентов и серверов OAuth2 и Spring Security OAuth2 . Некоторые из этих функций были перенесены из Spring Cloud Security и, следовательно, были в последовательности выпуска Spring Cloud от Angel , но не в версии Brixton. Эта статья поможет вам перемещаться по изменениям и обновлять любые существующие приложения, чтобы использовать новые функции.

Управление зависимостями

Если вы не используете Spring Cloud, вы можете просто изменить номер версии зависимости Spring Boot. Поскольку некоторые функции OAuth2 перенесены из Spring Cloud Security в Spring Boot в версии 1.3, скорее всего, все немного сложнее. А отдельные статьи посвящена модернизации Spring облачных приложений от Spring ботинке 1.2 до 1.3. Если вы используете релиз-релиз Spring Cloud Angel, вам следует обратиться к этой статье за ​​подробностями о том, как управлять зависимостями (независимо от каких-либо конкретных функций).

Сервер авторизации

Сервер авторизации OAuth2 отвечает в первую очередь за выдачу токенов доступа. Для этого он должен иметь возможность аутентифицировать клиентские приложения и (необязательно) пользователей.

Очень простой сервер авторизации OAuth2 с одним клиентом может быть реализован в соответствии с соглашением и некоторыми свойствами конфигурации в Spring Boot 1.3. Таким образом, действительно простой пример, такой как аутентичный сервер vanilla из Angular JS Spring Securrity Tutorial из spring.io, может быть несколько упрощен. В Spring Boot 1.2 мы имеем:

@SpringBootApplication
@RestController
@EnableResourceServer
public class AuthserverApplication {

  @Configuration
  @EnableAuthorizationServer
  protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Excep
      endpoints.authenticationManager(authenticationManager);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
      clients.inMemory()
        .withClient("acme")
          .secret("acmesecret")
          .authorizedGrantTypes("authorization_code", "refresh_token",
              "password")
          .scopes("openid").autoApprove(true);
    }

  }

  ...
}

В Spring Boot 1.3 у нас есть только:

@SpringBootApplication
@RestController
@EnableResourceServer
@EnableAuthorizationServer
public class AuthserverApplication {
  ...
}

и в application.properties:

security.oauth2.client.clientId: acme
security.oauth2.client.clientSecret: acmesecret
security.oauth2.client.authorized-grant-types: authorization_code,refresh_token,password
security.oauth2.client.scope: openid

Это сервер авторизации общего назначения, отлично подходит для демонстраций, но не очень реалистично на практике, поскольку у него есть только один клиент («acme»). Тем не менее, как способ быстро начать работу с OAuth2, приятно иметь возможность сделать так много с таким небольшим.

Чтобы расширить базовый пример и получить контроль над функциями Сервера авторизации, вам нужно всего лишь вернуться к старой версии Spring Boot 1.2 (любое приложение со своими собственными AuthorizationServerConfigurerфункциями отключает функции с автоматической настройкой).

Ресурсный сервер

Сервер ресурсов защищает свои конечные точки, запрашивая действительный токен доступа (созданный сервером авторизации).

Аналогично серверу авторизации, сервер ресурсов может быть реализован в соответствии с соглашением и некоторыми свойствами конфигурации в Spring Boot 1.3, а также с Spring Boot 1.2 в сочетании с Spring Cloud Security. В качестве примера рассмотрим ванильный сервер ресурсов Angular JS Spring Security Tutorial от spring.io.

В Spring Boot 1.2 нам пришлось использовать Spring Cloud Security для @EnableOAuth2Resourceаннотации:

@SpringBootApplication
@RestController
@EnableOAuth2Resource
class ResourceApplication {
  ...
}

и некоторая конфигурация, чтобы помочь декодировать токены доступа в application.properties

spring.oauth2.resource.userInfoUri: http://localhost:9999/uaa/user

В Spring Boot 1.3 зависимость Spring Cloud можно удалить, а аннотацию заменить на @EnableResourceServerванильную аннотацию из Spring Security OAuth2:

@SpringBootApplication
@RestController
@EnableResourceServer
class ResourceApplication {
  ...
}

Для завершения приложения есть немного другая конфигурация (обратите внимание, что префикс ключа изменяется с spring.oauth2на security.oauth2):

security.oauth2.resource.userInfoUri: http://localhost:9999/uaa/user

Клиентское приложение

В OAuth2 клиент — это агент (обычно приложение), который получает токен, часто от имени пользователя. Единый вход в систему может быть реализован с помощью одного Сервера авторизации и зависимых приложений аутентификации, которые являются клиентами OAuth2.

Ванильный единый вход

На стороне клиента в Spring Boot 1.3 вы можете реализовать шаблон единого входа с аннотацией и некоторыми свойствами конфигурации. Вы можете сделать то же самое с Spring Boot 1.2, если вы используете Spring Cloud Security.

Действительно общий пример с Spring Boot 1.2 и Spring Cloud Angel будет использовать одну @EnableOAuth2Ssoаннотацию:

@SpringBootApplication
@EnableOAuth2Sso
public class SsoApplication {
  ...
}

и некоторая конфигурация для клиента в application.yml(или эквивалентно application.properties). Вот пример аутентификации с помощью Facebook для приложения, работающего на localhost: 8080:

spring:
  oauth2:
    client:
      clientId: 233668646673605
      clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
      accessTokenUri: https://graph.facebook.com/oauth/access_token
      userAuthorizationUri: https://www.facebook.com/dialog/oauth
      tokenName: oauth_token
      authenticationScheme: query
      clientAuthenticationScheme: form
    resource:
      userInfoUri: https://graph.facebook.com/me

То же приложение выглядит почти одинаково в Spring Boot 1.3, но в Spring Cloud Security нет необходимости. Также аннотация перемещена в другой пакет, и префикс конфигурации изменился. Таким образом, удаление зависимости Cloud, изменение импорта аннотации и переключение префикса application.ymlс springна на security— это все, что необходимо для переноса этого приложения.

Правила единого входа и пользовательского доступа

В Spring Cloud Security 1.0 (из серии релизов Angel) пользователи могут настраивать соответствие запросов и правила доступа, используя комбинацию специального обратного вызова OAuth2ClientConfigurerи некоторых свойств конфигурации в spring.oauth2.sso.*. Так, например, в клиентском приложении vanilla из Angular JS Spring Security Tutorial от spring.io есть общий шаблон реализации в Spring Boot 1.2:

@SpringBootApplication
@EnableOAuth2Sso
public class UiApplication {

  @Configuration
  protected static class SecurityConfiguration extends OAuth2SsoConfigurerAdapter {

    @Override
    public void match(RequestMatchers matchers) {
      matchers.anyRequest();
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
      http
        .authorizeRequests()
          .antMatchers("/index.html", "/home.html", "/").permitAll()
          .anyRequest().authenticated()
        .and().csrf()
          .csrfTokenRepository(csrfTokenRepository())
        .and()
          .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
    }

  }

  ...

}

и похож application.ymlна ванильный образец:

spring:
   oauth2:
    sso:
      home:
        secure: false
        path: /,/**/*.html
     client:
       accessTokenUri: http://localhost:9999/uaa/oauth/token
       userAuthorizationUri: http://localhost:9999/uaa/oauth/authorize
     resource:
       userInfoUri: http://localhost:9999/uaa/user

В Spring Boot 1.3 нет необходимости в Spring Cloud Security, а настройки не нуждаются в устаревшем OAuth2SsoConfigurerAdapter. Вместо этого им просто нужен весь один и тот же код, а также сопоставитель запросов, в регулярном виде WebSecurityConfigurerAdapterс @EnableOAuth2Ssoаннотацией:

@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class UiApplication extends WebSecurityConfigurerAdapter {

  @Override
  public void configure(HttpSecurity http) throws Exception {
    http.antMatcher("/**")
      .authorizeRequests()
        .antMatchers("/index.html", "/home.html", "/").permitAll()
        .anyRequest().authenticated()
      .and().csrf()
        .csrfTokenRepository(csrfTokenRepository())
      .and()
        .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
  }

  ...

}

Свойства конфигурации в обновленной версии в основном одинаковы: изменение префикса с spring.oauth2на security.oauth2и нет необходимости в *.oauth2.sso.*свойствах, поскольку они явно настроены пользователем в WebSecurityConfigurerAdapter.

Единый вход и Zuul Proxy

Фактическое клиентское приложение в Angular JS Spring Security Tutorial от spring.io похоже на настраиваемое выше, но это также и прокси Zuul, отвечающий за пересылку запросов от клиента браузера во внутренние сервисы. В Spring Boot 1.3 этому приложению по-прежнему требуется Spring Cloud Security для ретрансляции токенов (оно хочет отправить токены доступа, используемые для аутентификации, на внутренние ресурсы), но оно не требуется для основных функций единого входа, поэтому реализация идентичен предыдущему образцу с добавлением @EnableZuulProxyаннотации.

Единый вход Один в Cloud Foundry

Spring Boot 1.2 и Spring Cloud Security в серии релизов Angel позволяют приложению настраивать себя для единого входа OAuth2, если вы привязываетесь к службе с правильными учетными данными. Например, вы можете создать предоставляемую пользователем услугу, например:

cf create-user-provided-service sso -p '{"userInfoUri":"https://uaa.run.pivotal.io/userinfo", "tokenUri":"login.run.pivotal.io/oauth/token", "authorizationUri":"login.run.pivotal.io/oauth/authorize", "clientId":"[client]", "clientSecret":"[secret]"}'

Затем приложение, с @EnableOAuth2Ssoкоторым связан сервис, свяжет конфигурацию, необходимую для единого входа, без необходимости изменения какой-либо конфигурации пользователем.

Та же функция доступна в Spring Boot 1.3 и Spring Cloud Brixton, но вместо Spring Cloud Security вам нужно использовать новую spring-cloud-cloudfoundry-webбиблиотеку для получения привязки конфигурации SSO. Вы также можете использовать встроенную службу единого входа в Cloud Foundry вместо предоставляемой пользователем службы (доступной в Pivotal Web Services для выбранных учетных записей или в Pivotal Cloud Foundry).

Вывод

Если вы используете Spring Boot и, возможно, Spring Cloud с OAuth2, надеюсь, вы теперь сможете плавно перейти с Spring Boot 1.2 на 1.3, или, в худшем случае, у вас будут некоторые инструменты, которые помогут вам думать о том, что происходит, когда вы нажимаете бугорки. Spring Boot 1.3 обладает практически всеми функциями Spring Cloud Security 1.0, поэтому главное, о чем вы должны подумать, — это зависимости. Кроме того, в Spring Boot есть несколько новых функций, таких как, например, автоконфигурация сервера авторизации. Как обычно в Spring Boot, вы можете (и должны) использовать настройку по умолчанию до тех пор, пока вам не потребуется ее изменить, и в этот момент для этого не должно быть никаких препятствий.

Все примеры приложений в руководствах Spring теперь обновлены до Spring Boot 1.3, даже если это означает, что они зависят от вехи Spring Cloud (это относится только к примеру прокси Zuul). Многим Spring Cloud больше не нужен. Если вам нужна версия Spring Cloud для GA, вам нужно использовать Spring Boot 1.2 прямо сейчас. Образцы для этой комбинации могут быть взяты из истории git.