Перейти к основному содержимому

Введение в OAuth2RestTemplate

· 5 мин. чтения

1. Обзор

В этом руководстве мы узнаем , как использовать Spring OAuth2RestTemplate для выполнения вызовов REST OAuth2 .

Мы создадим веб-приложение Spring, способное отображать репозитории учетной записи GitHub.

2. Конфигурация Maven

Во- первых, нам нужно добавить зависимости spring-boot-starter-security и spring-security-oauth2-autoconfigure в наш pom.xml . Поскольку мы создаем веб-приложение, нам также необходимо включить артефакты spring-boot-starter-web и spring-boot-starter-thymeleaf .

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

3. Свойства OAuth2

Далее давайте добавим конфигурацию OAuth в наш файл application.properties , чтобы можно было подключить учетную запись GitHub:

github.client.clientId=[CLIENT_ID]
github.client.clientSecret=[CLIENT_SECRET]
github.client.userAuthorizationUri=https://github.com/login/oauth/authorize
github.client.accessTokenUri=https://github.com/login/oauth/access_token
github.client.clientAuthenticationScheme=form

github.resource.userInfoUri=https://api.github.com/user
github.resource.repoUri=https://api.github.com/user/repos

Обратите внимание, что нам нужно заменить [ CLIENT_ID] и [CLIENT_SECRET] значениями из приложения GitHub OAuth. Мы можем следовать руководству по созданию приложения OAuth , чтобы зарегистрировать новое приложение на GitHub:

./a8c6340371066e115e255795ae26a2c9.png

Давайте удостоверимся, что для URL-адреса обратного вызова авторизации установлено значение http://localhost:8080, что перенаправит поток OAuth на домашнюю страницу нашего веб-приложения.

4. Конфигурация шаблона OAuth2Rest

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

4.1. Класс SecurityConfig _

Во-первых, давайте расширим WebSecurityConfigurerAdapter , чтобы воспользоваться помощниками конфигурации Spring:

@Configuration
@EnableOAuth2Client
public class SecurityConfig extends WebSecurityConfigurerAdapter {
OAuth2ClientContext oauth2ClientContext;

public SecurityConfig(OAuth2ClientContext oauth2ClientContext) {
this.oauth2ClientContext = oauth2ClientContext;
}

...
}

@EnableOAuth2Client дает нам доступ к контексту OAuth2, который мы будем использовать для создания нашего OAuth2RestTemplate .

4.2. Бин OAuth2RestTemplate

Во-вторых, мы создадим bean-компонент для нашего OAuth2RestTemplate :

@Bean
public OAuth2RestTemplate restTemplate() {
return new OAuth2RestTemplate(githubClient(), oauth2ClientContext);
}

@Bean
@ConfigurationProperties("github.client")
public AuthorizationCodeResourceDetails githubClient() {
return new AuthorizationCodeResourceDetails();
}

При этом мы используем свойства и контекст OAuth2 для создания экземпляра шаблона.

Аннотация @ConfigurationProperties внедряет все свойства github.client в экземпляр AuthorizationCodeResourceDetails .

4.3. Фильтр аутентификации

В-третьих, нам нужен фильтр аутентификации для обработки потока OAuth2:

private Filter oauth2ClientFilter() {
OAuth2ClientAuthenticationProcessingFilter oauth2ClientFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/github");
OAuth2RestTemplate restTemplate = restTemplate();
oauth2ClientFilter.setRestTemplate(restTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(githubResource().getUserInfoUri(), githubClient().getClientId());
tokenServices.setRestTemplate(restTemplate);
oauth2ClientFilter.setTokenServices(tokenServices);
return oauth2ClientFilter;
}

@Bean
@ConfigurationProperties("github.resource")
public ResourceServerProperties githubResource() {
return new ResourceServerProperties();
}

Здесь мы указываем фильтру инициировать поток OAuth2 по URL-адресу /login/github нашего приложения.

4.4. Конфигурация безопасности Spring

Наконец, давайте зарегистрируем OAuth2ClientContextFilter и создадим конфигурацию веб-безопасности:

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/login**", "/error**")
.permitAll().anyRequest().authenticated()
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
.and().addFilterBefore(oauth2ClientFilter(), BasicAuthenticationFilter.class);
}

@Bean
public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(filter);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
return registration;
}

Мы защищаем пути наших веб-приложений и гарантируем, что OAuth2ClientAuthenticationProcessingFilter зарегистрирован перед BasicAuthenticationFilter .

5. Использование шаблона OAuth2RestTemplate

Основная цель OAuth2RestTemplate — сократить объем кода, необходимого для выполнения вызовов API на основе OAuth2 . Это в основном удовлетворяет две потребности для нашего приложения:

  • Обрабатывает поток аутентификации OAuth2.
  • Расширяет Spring RestTemplate для выполнения вызовов API

Теперь мы можем использовать OAuth2RestTemplate в качестве автоматически подключаемого компонента в веб-контроллере.

5.1. Авторизоваться

Давайте создадим файл index.html с параметрами входа и дома:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>OAuth2Client</title>
</head>
<body>
<h3>
<a href="/login/github" th:href="@{/home}" th:if="${#httpServletRequest?.remoteUser != undefined }">
Go to Home
</a>
<a href="/hello" th:href="@{/login/github}" th:if="${#httpServletRequest?.remoteUser == undefined }">
GitHub Login
</a>
</h3>
</body>
</html>

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

5.2. Дом

Теперь давайте создадим контроллер для приветствия аутентифицированного пользователя GitHub:

@Controller
public class AppController {

OAuth2RestTemplate restTemplate;

public AppController(OAuth2RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

@GetMapping("/home")
public String welcome(Model model, Principal principal) {
model.addAttribute("name", principal.getName());
return "home";
}
}

Обратите внимание, что у нас есть параметр безопасности Principal в методе приветствия . Мы используем имя принципала в качестве атрибута модели пользовательского интерфейса.

Давайте посмотрим на шаблон home.html :

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<p>
Welcome <b th:inline="text"> [[${name}]] </b>
</p>
<h3>
<a href="/repos">View Repositories</a><br/><br/>
</h3>

<form th:action="@{/logout}" method="POST">
<input type="submit" value="Logout"/>
</form>
</body>
</html>

Кроме того, мы добавляем ссылку для просмотра списка репозиториев пользователя и возможность выхода из системы.

5.3. Репозитории GitHub

Теперь пришло время использовать шаблон OAuth2RestTemplate, созданный в предыдущем контроллере, для представления всех репозиториев GitHub, принадлежащих пользователю.

Во-первых, нам нужно создать класс GithubRepo для представления репозитория:

public class GithubRepo {
Long id;
String name;

// getters and setters

}

Во-вторых, давайте добавим сопоставление репозиториев с предыдущим AppController :

@GetMapping("/repos")
public String repos(Model model) {
Collection<GithubRepo> repos = restTemplate.getForObject("https://api.github.com/user/repos", Collection.class);
model.addAttribute("repos", repos);
return "repositories";
}

OAuth2RestTemplate обрабатывает весь шаблонный код для выполнения запроса к GitHub . Кроме того, он преобразует ответ REST в коллекцию GithubRepo .

Наконец, давайте создадим шаблон repositories.html для перебора коллекции репозиториев:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Repositories</title>
</head>
<body>
<p>
<h2>Repos</h2>
</p>
<ul th:each="repo: ${repos}">
<li th:text="${repo.name}"></li>
</ul>
</body>
</html>

6. Заключение

В этой статье мы узнали, как использовать OAuth2RestTemplate для упрощения вызовов REST к серверу ресурсов OAuth2, такому как GitHub.

Мы рассмотрели строительные блоки веб-приложения, использующего поток OAuth2. Затем мы увидели, как сделать вызов REST API для получения всех пользовательских репозиториев GitHub.

Как всегда, полный пример этого руководства можно найти на GitHub .