В этом руководстве мы рассмотрим различные способы добавления функции входа в систему с помощью Spring Boot 2.1.
Сначала мы создадим страницу аутентификации на основе форм. Затем мы настроим автоматически сгенерированную форму, отменив некоторые стандартные контроллеры и шаблоны. И, наконец, вы будете использовать OAuth 2.0 для единого входа (SSO). Мы также покажем вам, как разрешить пользователю входить в систему, используя GitHub и Okta .
Что вам нужно для начала:
1. Иметь общее представление о Spring и Spring Boot
2. Установите git. Вы также можете установить Gradle, но это не является обязательным требованием, поскольку вы можете использовать оболочку Gradle для всех команд Gradle.
Идем дальше и клонируем репозиторий, который я создал для этого урока:
git clone https://github.com/oktadeveloper/okta-spring-boot-login-options-example.git
Этот репозиторий содержит пять подкаталогов:
basic-auth
form-auth
custom-form-auth
oauth-start
oauth-okta-github
oauth-okta-starter
Они соответствуют четырем разделам этого руководства (три из них для последнего раздела, раздел OAuth). За исключением oauth-start
, это полностью функциональные приложения. В этом уроке вы узнаете, что означает код и как его создавать.
Создать базовый вход HTTP в Spring Boot
Базовая аутентификация, ну, в общем, базовая. Это простая схема, встроенная непосредственно в протокол HTTP. Это происходит из пастырских времен, когда огромные объемы данных и денег текли по различным каналам Интернета. Таким образом, это действительно не невероятно безопасно. Согласно спецификации, пароль и имя пользователя кодируются с использованием Base64 в authorization
заголовке HTTP . Поскольку Base64 также может быть простым текстом, если вы собираетесь использовать базовую аутентификацию для чего-либо, убедитесь, что вы всегда используете HTTPS / SSL, потому что вы отправляете свои учетные данные для аутентификации при каждом запросе.
Откройте проект basic-auth
Spring Boot с вашей любимой IDE или редактором.
Первое, что вы захотите проверить, это build.gradle
файл. Это воспроизведено ниже. Я не буду подробно останавливаться на всех из них, но хочу сориентировать вас на несколько вещей, происходящих здесь, на случай, если вы еще не знакомы.
plugins {
id 'org.springframework.boot' version '2.1.4.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.okta.springsecurityauth'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
В сборку добавляются два плагина Spring: org.springframework.boot
и io.spring.dependency-management
. Обратите внимание, что версия установлена в 2.1.4.RELEASE
. Одна из настоящих проблем со Spring в прошлом — управление зависимостями. Spring — это огромная коллекция библиотек, и, когда вы вносите одну, вам нужно вводить другие с совместимыми версиями. Когда вы обновляете один, часто это приводит к тому, что другие выходят из-под совместимости Исправив это в прошлом, вы попадете в так называемый «ад зависимости».
К счастью, весна сделала вещи намного проще. Посмотрите на наши две зависимости Spring:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
...
}
Обратите внимание, что у них нет номеров версий. Это в основном большие мета-зависимости для наборов функций (в данном случае для безопасности и для веб-сайтов), и плагины Spring управляют всеми вашими зависимостями на основе версии, установленной в этой строке:
id 'org.springframework.boot' version '2.1.4.RELEASE'
Резюме всего этого заключается в том, что этот build.gradle
файл будет загружать Spring Boot версии 2.1.4 и будет добавлять веб-модули и функциональные модули безопасности. Список всех доступных стартеров из Spring можно найти в их документах .
Кроме этого gradle.file
, есть только три других файла, представляющих интерес, все файлы Java. Посмотрите внизу, src/main/java/com/okta/springsecurityauth
и вы увидите их:
Application.java
(основной класс, который автоматически создает магический фреймворк Spring Boot)SecurityConfiguration.java
(настраивает параметры безопасности)WebController.java
(очень простой контроллер HTTP-запросов)
Application.java
является точкой входа в приложение. В этом случае все довольно просто, и во многих случаях наиболее важной является @SpringBootApplication
аннотация, которая сообщает вашим зависимостям Spring для начальной загрузки всей среды Spring Boot. Есть, конечно, и main()
метод, в котором Application
класс загружается и запускается Spring.
package com.okta.springsecurityauth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
WebController.java
это, достаточно умно, ваш контроллер веб-запросов. Он определяет конечные точки запроса и определяет ответы.
package com.okta.springsecurityauth;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class WebController {
@RequestMapping("/")
@ResponseBody
public String index() {
return "That's pretty basic!";
}
}
В этом случае веб-контроллер возвращает простую строку вместо маршрутизации в файл шаблона, как мы увидим чуть позже. @ResponseBody
Аннотация что позволяет этот метод непосредственно возвращает строку.
SecurityConfiguration.java
где действие происходит в этом уроке. Здесь Spring Boot настроен для использования базовой аутентификации. Здесь также можно настроить жестко заданные имя пользователя и пароль по умолчанию (очевидно, это не то, что я бы делал в работе, но отлично подходит для обучающих программ).
package com.okta.springsecurityauth;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("{noop}pass") // Spring Security 5 requires specifying the password storage format
.roles("USER");
}
}
Если вы посмотрите на configure()
метод, вы увидите, что http
объект используется с его свободно распространяемым интерфейсом, чтобы сказать Spring аутентифицировать все запросы и использовать базовую аутентификацию HTTP. Это довольно тривиально, но в этом интерфейсе есть тонны мощности, как вы увидите через минуту.
Этот configure()
учебник, в основном, предназначен для создания пользователя в диспетчере аутентификации в памяти. Вы создаете пользователя с именем пользователя user
и паролем pass
. Пользователь имеет USER
назначенную ему роль.
Это оно!
Откройте терминал и убедитесь, что вы находитесь в корневом каталоге basic-auth
проекта. Запустите проект с помощью следующей команды:
./gradlew bootRun
Подождите, пока приложение Spring Boot завершит загрузку.
Перейдите к http://localhost:8080
.
Вы увидите окно входа в систему.
Войдите, используя user
и pass
как учетные данные.
Вы попадете на экран успеха, который говорит: «Это довольно просто!»
Настройка входа в Spring Spring на основе форм
При использовании базовой аутентификации форма входа в систему фактически создается браузером, а не приложением. Появляется как не стилизованное всплывающее окно. Это не отличный поток или очень профессиональный вид.
С некоторыми довольно минимальными изменениями в коде Spring Boot может автоматически генерировать более профессионально выглядящую форму входа. Завершенный код можно найти в form-auth
подкаталоге репозитория GitHub, или вы можете просто внести изменения в basic-auth
проект, если он все еще открыт.
Вы хотите изменить configure()
метод SecurityConfiguration.java
файла, чтобы он выглядел так:
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
Разница лишь в добавлении .and().formLogin()
. Кроме этого, два проекта одинаковы.
Запустите его снова, используя ./gradlew bootRun
.
Перейдите к http://localhost:8080
(вам может понадобиться открыть окно инкогнито для запуска повторной аутентификации).
На этот раз вы увидите страницу входа, которую Spring генерирует для вас.
Настройка формы входа в Spring Boot
Следующим шагом на пути к все более изощренной аутентификации Spring Boot является настройка формы входа. Весна делает это супер легко. Однако, есть несколько новых файлов и больше изменений в коде, чем в прошлый раз, поэтому я бы предложил открыть проект, находящийся в custom-form-auth
папке репозитория.
В build.gradle
файле есть одна новая зависимость. В результате появился шаблонизатор Thymeleaf, веб-шаблонизатор по умолчанию для использования с Spring Boot.
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
...
}
SecurityConfiguration.java
Файл теперь выглядит следующим образом (с некоторыми частями опущенными для краткости):
package com.okta.springsecurityauth;
...
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.failureUrl("/login-error.html")
.permitAll();
}
...
}
Обратите внимание, что .httpBasic()
ушел, и .formLogin()
есть некоторые новые опции. Здесь вы настраиваете страницу входа и страницу сбоя при входе в систему и делаете их общедоступными.
Также обратите внимание на эту строку:
.antMatchers( "/public/**").permitAll()
Здесь вы делаете public
каталог в корневом каталоге пути доступным без аутентификации. Под src/main/resources/static
, есть public
каталог. Когда приложение запускается, все в src/main/resources/static
каталоге копируется в classpath, поэтому public
каталог попадает в корень classpath, и все файлы в нем будут доступны без аутентификации. Это отлично подходит для таких вещей, как изображения, файлы JavaScript и файлы CSS.
WebController.java
Также имеет некоторые новые конечные точки:
package com.okta.springsecurityauth;
...
@Controller
public class WebController {
@RequestMapping("/")
@ResponseBody
public String index() {
return "You made it!";
}
// Login form
@RequestMapping("/login.html")
public String login() {
return "login.html";
}
// Login form with error
@RequestMapping("/login-error.html")
public String loginError(Model model) {
model.addAttribute("loginError", true);
return "login.html";
}
}
Обратите внимание , что в то время как index()
метод имеет @RequestBody
аннотацию, а это означает , что он собирается вернуть свое тело запроса непосредственно в виде строки, login()
и loginError()
методы не делают. Вместо этого они возвращают имя шаблонов Thymeleaf, которые будет отображаться Spring Boot. По умолчанию эти шаблоны находятся в разделе src/main/resources/templates
. Кроме того, обратите внимание, что loginError()
это немного уловка маршрутизации. На самом деле он просто возвращает login.html
шаблон, но с атрибутом ошибки, введенным в модель.
src/main/resources/templates/login.html
это новый файл Это файл шаблона входа.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login page</title>
<link th:href="@{/public/style.css}" rel="stylesheet" />
</head>
<body>
<div id="container">
<h2>Login page</h2>
<form th:action="@{/login.html}" method="post">
<label for="username">Username</label>
<input type="text" id="username" name="username" autofocus="autofocus" />
<label for="password">Password</label>
<input type="password" id="password" name="password" />
<input id="submit" type="submit" value="Log in" />
</form>
<p th:if="${loginError}" class="error">Wrong user or password</p>
</div>
</body>
</html>
Настоящее подробное объяснение Thymeleaf выходит далеко за рамки данного руководства. Зайдите на их сайт, чтобы покопаться в нем, если хотите.
Помните, когда вы сделали public
каталог общедоступным? Здесь есть очень простая таблица стилей, которую вытащил эта строка. В основном я включил это, чтобы продемонстрировать один из способов включения статических ресурсов в файлы шаблонов.
<link th:href="@{/public/style.css}" rel="stylesheet" />
Строка ошибки отображается условно на основе loginError
атрибута модели, который вводится loginError()
методом контроллера.
<p th:if="${loginError}" class="error">Wrong user or password</p>
Кроме этого, это довольно простая форма входа!
Еще раз, ./gradlew bootRun
чтобы запустить его.
Вы увидите стилизованную, настроенную форму входа в систему:
Войдите снова, используя, user:pass
и вы увидите наш экран успеха, говорящий: «Вы сделали это!»
Вход в Spring Boot OAuth 2.0 с использованием GitHub и единого входа
До этого момента все ваши аутентификации выполнялись локально с использованием специальной памяти AuthenticationManager
. Чаще всего в производстве приложения поддерживают OAuth 2.0 и OIDC (Open ID Connect). OAuth 2.0 — это открытый стандарт для авторизации. OIDC построен на основе OAuth 2.0 и добавляет аутентификацию для более полного протокола управления идентификацией.
В этом руководстве вы сначала увидите, как добавить систему единого входа (SSO) с помощью GitHub. После этого вы узнаете, как использовать Okta , поставщика решений для идентификации программного обеспечения.
И то, и другое очень просто, и есть реальная выгода, позволяющая пользователям повторно использовать существующих поставщиков удостоверений. Заставлять пользователей обрабатывать и управлять отдельными надежными паролями для сотен веб-сайтов — это глупое поручение, которое в конечном итоге приводит к тому, что более слабые пароли и пароли повторно используются на нескольких сайтах (что увеличивает их уязвимость к атакам); не говоря уже о старом «просто набросать его на заметку и прикрепить его к монитору» решение для управления паролями
Упростите вход в приложение Spring Boot с помощью единого входа GitHub
Теперь пришло время реализовать клиент GitHub OAuth 2.0.
Во-первых, вам нужно зарегистрировать новое приложение OAuth в GitHub. Зайдите на их сайт и сделайте это сейчас. Заполните значения, как показано ниже.
Обратите особое внимание на URL обратного вызова авторизации, как это должно быть http://localhost:8080/login/oauth2/code/github
.
Нажмите Зарегистрировать приложение. Запишите идентификатор клиента и секрет клиента, так как они понадобятся вам в течение секунды.
Теперь вернемся к Java. Откройте oauth-start
проект в вашей IDE.
В build.gradle
файле обратите внимание на пару новых зависимостей:
...
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.security:spring-security-oauth2-client'
implementation 'org.springframework.security:spring-security-oauth2-jose'
...
}
Безопасность, Thymeleaf и веб-стартеры все еще там. Тем не менее, есть два новых начала весны: oauth2-client
и oauth2-jose
.
oauth2-client
приносит библиотеки, необходимые для реализации клиента OAuth 2.0. oauth2-jose
приносит некоторые общие библиотеки для подписи и шифрования. JOSE расшифровывается как Java Object Signing и Encryption.
SecurityConfiguration.java
Файл был обновлен для OAuth входа в систему :
package com.okta.spring.SpringBootOAuth;
...
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
Обратите внимание на две вещи: 1) все запросы /
и login
являются общедоступными, и 2) oauth2Login()
метод — это то, что заставляет Spring Boot настроить клиент OAuth 2.0.
Если это кажется слишком простым , вы правы. Часть конфигурации была перемещена в application.yml
файл.
Откройте src/main/resources/application.yml
файл:
spring:
thymeleaf:
cache: false
security:
oauth2:
client:
registration:
github:
client-id: << your GitHub client ID>>
client-secret: << your GitHub client secret >>
Вам необходимо указать идентификатор клиента и секрет клиента сверху в этом файле.
Интернет-маршрутизация и шаблоны также изменились. Посмотрите на WebController.java
файл:
package com.okta.spring.SpringBootOAuth;
...
@Controller
public class WebController {
@RequestMapping("/securedPage")
public String securedPage(Model model,
@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,
@AuthenticationPrincipal OAuth2User oauth2User) {
model.addAttribute("userName", oauth2User.getName());
model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());
model.addAttribute("userAttributes", oauth2User.getAttributes());
return "securedPage";
}
@RequestMapping("/")
public String index() {
return "index";
}
}
Этот контроллер определяет две конечные точки, которые возвращают два файла шаблона:
/
->src/main/resources/templates/index.html
/securedPage
->src/main/resources/templates/securedPage.html
В этом securedPage()
методе обратите внимание на то, как внедрение зависимостей используется для получения информации об аутентифицированном пользователе, чтобы ее можно было внедрить в модель, которая затем передается в файл шаблона.
Это src/main/resources/templates/index.html
довольно просто:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>Spring Security SSO</h1>
<a href="securedPage">Login</a>
</body>
</html>
И src/main/resources/templates/securedPage.html
файл шаблона:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Secured Page</title>
</head>
<body>
<h1>Secured Page</h1>
<div>User Name: <span th:text="${userName}"></span></div>
<div>Client Name: <span th:text="${clientName}"></span></div>
<div>User Attributes: <span th:text="${userAttributes}"></span></div>
</body>
</html>
Теперь вы готовы попробовать это. Опять же, убедитесь, что вы находитесь в корне проекта, и запустите ./gradlew bootRun
.
Перейдите http://localhost:8080
и нажмите на ссылку «Войти».
Если ваш браузер обходит страницу входа и сразу переходит к /securedPage
конечной точке, откройте браузер инкогнито и попробуйте снова.
Во-первых, вам необходимо авторизовать приложение Spring Boot Login, чтобы использовать вашу учетную запись GitHub для входа в OAuth.
Далее вы увидите экран входа в GitHub OAuth:
Если вы добились успеха, вы увидите простую текстовую страницу с надписью «Защищенная страница», выделенную жирным шрифтом и отображающую некоторую информацию о вашем пользователе OAuth.
Довольно мило, а?
Теперь вы собираетесь добавить второго поставщика OAuth: Okta.
Добавьте OAuth 2.0, войдите с Okta в приложение Spring Boot
Сначала зайдите на сайт developer.okta.com и зарегистрируйте бесплатную учетную запись разработчика, если у вас ее еще нет.
Если у вас есть учетная запись, чтобы создать приложение OAuth / OIDC, откройте панель инструментов разработчика Okta. Нажмите на верхний пункт меню Приложения, а затем нажмите Добавить приложение.
Выберите Web в качестве платформы и нажмите Next.
Дайте приложению имя. Я назвал мой «Spring Boot Login», но вы можете назвать свой как угодно.
Измените URI перенаправления входа в систему на http://localhost:8080/login/oauth2/code/okta
.
Другие значения по умолчанию в порядке.
Нажмите Готово.
Запишите идентификатор клиента и секрет клиента на следующей странице.
Обновите application.yml
файл для Okta:
spring:
...
security:
oauth2:
client:
registration:
github:
client-id: << Your GitHub Client ID >>
client-secret: << Your GitHub Client Secret >>
okta:
client-id: << Your Okta Client ID >>
client-secret: << Your Okta Client Secret >>
client-name: Okta
provider:
okta:
issuer-uri: https://okta.okta.com/oauth2/default
Вам необходимо добавить регистрацию Okta и записи провайдера, убедившись, что вы указали свой Client ID, Client Secret и издателя Okta.
Перезапустите приложение, перейдите по http://localhost:8080
ссылке и нажмите ссылку «Вход».
На этот раз вам будет предоставлен выбор поставщиков услуг OAuth. Этот экран автоматически генерируется Spring Boot.
Нажмите Okta, и вы попадете на страницу входа в Okta (обычное предупреждение о выходе из системы и / или применении в режиме инкогнито).
Авторизуйтесь, и вы увидите нашу страницу успеха.
На данный момент вы обновили oauth-start
проект с помощью oauth-github-okta
папки проекта и увидели, как легко добавить несколько поставщиков OAuth в приложение Spring Boot.
Упрощение входа в OAuth 2.0 с помощью весеннего загрузчика Okta
Последнее, что вы собираетесь сделать в этом руководстве, — это настроить Okta для разрешения регистрации новых пользователей. Однако прежде чем вы это сделаете, я хочу познакомить вас с Okta Spring Boot Starter. Проект упрощает интеграцию Spring Boot и Okta. README проекта — отличный источник для более подробной информации.
Вы собираетесь интегрировать загрузчик Okta Spring в этот проект и немного упростить настройку. Просто для простоты вы также удалите интеграцию GitHub OAuth.
Добавьте одну зависимость в build.gradle
файл:
dependencies {
...
implementation 'com.okta.spring:okta-spring-boot-starter:1.1.0'
...
}
Теперь обновите application.yml
файл:
okta:
oauth2:
issuer: https://okta.okta.com/oauth2/default
client-id: <<yourOktaClientID>>
client-secret: <<yourOktaClientSecret>>
spring:
thymeleaf:
cache: false
Заполните свой секрет клиента и идентификатор клиента.
Попытайся. Беги ./gradlew bootRun
.
Вы должны быть в состоянии войти через Okta. На этот раз вам не будет предоставлен выбор поставщиков OAuth 2.0.
Включить регистрацию пользователя
Войдите в свою учетную запись developer.okta.com .
Наведите указатель мыши на пользователя и нажмите «Регистрация».
Включить регистрацию. Кроме того, включите ссылку «Показать» на странице входа…. Это приводит к тому, что ссылка для регистрации отображается на странице входа в систему.
Войдите снова, используя окно инкогнито. На этот раз вы заметите, что у пользователя есть возможность зарегистрироваться в качестве нового пользователя.
Введите адрес электронной почты, пароль и имя; Задайте несколько вопросов безопасности, и все готово! Вы зарегистрировали нового пользователя для своего приложения, используя Okta.
Вы можете сделать гораздо больше с помощью опций регистрации в Okta. Все это можно настроить и настроить. Посмотрите на их документы, чтобы копать глубже.
Конечный продукт для этого с помощью Okta Spring Boot Starter и с удаленным GitHub OAuth находится в oauth-okta-starter
каталоге.
Узнайте больше о параметрах входа в Spring Boot и безопасной аутентификации
Вы покрыли тонну территории в этом уроке. Вы реализовали приложение Spring Boot, используя базовую аутентификацию, аутентификацию на основе форм и настраиваемую аутентификацию на основе форм. Затем вы использовали OAuth 2.0 и OIDC для реализации единого входа с использованием GitHub и Okta. Наконец, вы увидели, как Okta Spring Boot Starter можно использовать для упрощения настройки единого входа OAuth / OIDC в Spring Boot, и как позволить пользователям самостоятельно регистрироваться в Okta.
Вы можете найти весь код для примеров в этом руководстве на GitHub .
Чтобы глубже изучить создание пользовательских форм входа в систему, ознакомьтесь с документацией Spring по этому вопросу.
Образец Spring Security oauth2login также содержит много полезной информации и примеров.
Вот некоторые связанные сообщения в блоге, которые демонстрируют, как использовать Spring Boot и Spring Security для входа в систему и аутентификации:
- Простая аутентификация токена для приложений Java
- Создайте веб-приложение с помощью Spring Boot и Spring Security за 15 минут
- Создать безопасный Spring REST API
- Создайте простое приложение CRUD с помощью Spring Boot и Vue.js
Если вам понравился этот пост, подпишитесь на нас в социальных сетях { Twitter , Facebook , LinkedIn , YouTube }, чтобы узнать, когда мы публиковали подобные сообщения.
Краткое руководство по параметрам входа в Spring Boot было первоначально опубликовано в блоге разработчиков Okta 15 мая 2019 года.