В сентябре этого года группа наших разработчиков посетила 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.