{"id":349961,"date":"2023-07-08T03:00:31","date_gmt":"2023-07-08T03:00:31","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=349961"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=349961","title":{"rendered":"<span>\u0421\u0442\u0440\u043e\u0438\u043c \u0441\u0432\u043e\u0439 SSO. \u0427\u0430\u0441\u0442\u044c 2: PostgreSQL \u0438 \u0440\u043e\u043b\u0435\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u0438 \u043c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u043d\u0430\u0448\u0443 \u0441\u0435\u0440\u0438\u044e \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e SSO. \u0412 <a href=\"https:\/\/habr.com\/ru\/articles\/737548\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043e\u0441\u043d\u043e\u0432\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043d\u044e\u0430\u043d\u0441\u043e\u0432 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u043a \u0441 <code>Spring Authorization Server<\/code>, \u0442\u0430\u043a \u0438 \u0441 <code>Spring Security<\/code>, <code>Spring OAuth2 Client<\/code>. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 &#171;Social login&#187; \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e SSO \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>\u041d\u043e, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043e\u043a\u0443\u043d\u0451\u043c\u0441\u044f \u0432 \u043c\u0438\u0440 Spring, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u0438 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u0442\u0430\u0442\u0443\u0441<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 Spring Boot \u0438 Spring Authorization Server<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u043d\u0438 \u0441\u043b\u0435\u0433\u043a\u0430 \u043f\u043e\u0434\u043d\u044f\u043b\u0438\u0441\u044c: Spring Boot <code>3.1.1<\/code> \u0438 Spring Authorization Server <code>1.1.1<\/code>. \u041c\u044b \u0438\u0445 \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Java 17<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 SPA Vue.JS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0444\u0440\u043e\u043d\u0442\u0430 SSO<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Redis \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u044d\u0448 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 (\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u0442.\u0434.)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 PostgreSQL \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c Swagger \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0442\u0430\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u0442\u0430\u0442\u0443\u0441<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 SSO \u0447\u0435\u0440\u0435\u0437 \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430\/\u043f\u0430\u0440\u043e\u043b\u044f<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 SSO \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 OAuth2.1 \u0434\u043b\u044f \u043c\u043e\u0438\u0445 pet-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0430\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u043d\u0430 SSO. \u041c\u044b \u0435\u0433\u043e \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 vuejs \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (test-client). \u041d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c OAuth2 Resource Server<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u043f\u043e \u0442\u043e\u043a\u0435\u043d\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 SSO<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u043e\u0440\u043c\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 SSO<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438 (\u043e\u0442\u0437\u044b\u0432 \u0442\u043e\u043a\u0435\u043d\u0430, \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0435\u0441\u0441\u0438\u0439 \u0438 \u0442.\u0434.)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0430\u0448\u0435 \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435, \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u0432 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435.<\/p>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 2.1: \u0421\u043a\u0440\u0435\u0441\u0442\u0438\u043c \u043d\u0430\u0448 SSO \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 OAuth2 Resource Server<\/h3>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 SSO \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <code>Spring Authorization Server<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c introspection endpoint \u043f\u043e\u043c\u0438\u043c\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u0412 Spring Security \u0435\u0441\u0442\u044c <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/servlet\/oauth2\/resource-server\/index.html\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0434\u043f\u0440\u043e\u0435\u043a\u0442<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0435\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0438\u043c\u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f\u043c\u0438 (authorities) \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0439, \u0442\u0430\u043a\u043e\u043c\u0443 \u043a\u0430\u043a\u0438\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u0443 \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0448 SSO. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u043c \u0435\u0433\u043e \u0441 \u043d\u0430\u0448\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0439.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435: <code>j-service<\/code>. \u041e\u043d \u0438 \u0431\u0443\u0434\u0435\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0438\u043c Resource Server. \u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 <code>j-sso<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f web \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u0430\u043b\u0435\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c OAuth2 Resource Server:<\/p>\n<p><strong>j-service\/pom.xml<\/strong><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">     \/\/ .....     &lt;dependencies>         &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-starter-oauth2-resource-server&lt;\/artifactId>             &lt;version>3.0.6&lt;\/version>         &lt;\/dependency>     &lt;\/dependencies> &lt;\/project>  <\/code><\/pre>\n<p>\u0412\u0435\u0441\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b <code>j-service<\/code> \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-2.1\/j-service\/pom.xml\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/servlet\/oauth2\/resource-server\/opaque-token.html\" rel=\"noopener noreferrer nofollow\">OAuth 2.0 Resource Server<\/a>. \u0421\u0440\u0430\u0437\u0443 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u0432 \u043d\u0430\u0448\u0435\u043c <code>j-sso<\/code> \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b opaque tokens. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b Opaque Token \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0448 <code>j-service<\/code>. \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e: \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0448 <code>application.yml<\/code> \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <code>spring.security.oauth2.resourceserver.opaquetoken.*<\/code> \u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0445, \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<p><strong>application.yml<\/strong><\/p>\n<pre><code class=\"yaml\">\/\/ .....  spring:   security:     oauth2:       resourceserver:         opaquetoken:           client-id: test-client           client-secret: test-client           introspection-uri: http:\/\/localhost:7777\/oauth2\/token-info <\/code><\/pre>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0449\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Spring Security (\u043e\u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043d\u0438\u0436\u0435). \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 <code>sessionManagement<\/code>. \u0422\u0430\u043a \u043a\u0430\u043a security \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 <code>Authorization<\/code> \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u0441 \u0442\u0438\u043f\u043e\u043c <code>Bearer<\/code>, \u0442\u043e \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 <code>HttpSession<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Spring Security \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043c\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0438 <code>STATELESS<\/code>, \u0447\u0442\u043e\u0431\u044b Spring Security \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b <code>HttpSession<\/code> \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0435\u0433\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f <code>SecurityContext<\/code>. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c <code>JSESSIONID<\/code> Cookie \u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0438 Security \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <code>HttpSessionSecurityContextRepository<\/code>, <code>SessionManagementFilter<\/code> \u0438 <code>RequestCacheFilter<\/code>.<\/p>\n<p><code><strong>ResourceServerConfig<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Configuration @EnableWebSecurity @RequiredArgsConstructor public class ResourceServerConfig {      @Bean     public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {         \/\/ \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u0435\u0441\u0441\u0438\u0439         http.sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))                 .authorizeHttpRequests(customizer -> {                     customizer.anyRequest().authenticated();                 });          \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 OAuth2 Resource Server \u0441 Opaque Token         http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::opaqueToken);         return http.build();     } } <\/code><\/pre>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 main \u043a\u043b\u0430\u0441\u0441 &#8212; <code>ResourceApplication<\/code> \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441\u043e \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u0438\u043c endpoint-\u043e\u043c &#8212; <code>\/test<\/code>. \u041a\u043e\u0434 \u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0430\u043d\u0430\u043b\u0435\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0445 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.1\/j-service\/src\/main\/java\/ru\/dlabs\/sas\/example\/jservice\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>.<\/p>\n<p>\u0421\u043e\u0431\u0435\u0440\u0451\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 <code>j-sso<\/code> \u0438 <code>j-service<\/code>. \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043d\u0438\u0436\u0435\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043c Access Token. \u041d\u0430\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u0432\u0430\u0436\u043d\u043e \u043a\u0430\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 grant type, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u044d\u0442\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u0439\u0434\u0451\u043c \u043f\u043e \u043f\u0443\u0442\u0438 \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u0441 grant type \u0440\u0430\u0432\u043d\u044b\u043c <code>client_credentials<\/code>.<\/p>\n<pre><code>curl --location --request POST 'http:\/\/localhost:7777\/oauth2\/token?grant_type=client_credentials' \\ --header 'Authorization: Basic dGVzdC1jbGllbnQ6dGVzdC1jbGllbnQ=' <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\/\u043e\u0442\u0432\u0435\u0442\u0430 \u0438\u0437 Postman<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/a87\/c0b\/b5e\/a87c0bb5e777d032c944cea8ca4789f6.png\" alt=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\" title=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/a87\/c0b\/b5e\/a87c0bb5e777d032c944cea8ca4789f6.png\"\/><\/p>\n<div><figcaption>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a <code>Authorization<\/code> \u0441 \u0442\u0438\u043f\u043e\u043c <code>Basic<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f base64 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430: <code>test-client:test-client<\/code>. \u042d\u0442\u043e \u043d\u0430\u0448\u0438 <code>clientId<\/code> \u0438 <code>clientSecret<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 <code>j-sso<\/code>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 endpoint \u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043b\u043e\u0433\u0438.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/e0d\/139\/f23\/e0d139f235f0ea3a6c28b6737c8b7ff8.png\" alt=\"\u041b\u043e\u0433\u0438 j-service\" title=\"\u041b\u043e\u0433\u0438 j-service\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e0d\/139\/f23\/e0d139f235f0ea3a6c28b6737c8b7ff8.png\"\/><\/p>\n<div><figcaption>\u041b\u043e\u0433\u0438 j-service<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u0448 <code>j-service<\/code>, \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0437\u0430\u043f\u0440\u043e\u0441. \u0414\u0430\u043b\u0435\u0435 \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 <code>HTTP POST http:\/\/localhost:7777\/oauth2\/token-info<\/code>. \u0412 \u043d\u0435\u0433\u043e \u043e\u043d \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442 \u0442\u043e\u0442 access \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u0441 \u043a\u043e\u0434\u043e\u043c <code>200 OK<\/code>. \u0418 \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 <code>java.lang.ClassCastException<\/code>. \u0418\u0442\u0430\u043a, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0449\u0430\u044e\u0442\u0441\u044f, \u043d\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 Introspection Endpoint \u043d\u0430\u0448\u0435\u0433\u043e <code>j-sso<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u043f\u043e\u0447\u0435\u043c\u0443.<\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0432 \u0433\u043b\u0430\u0432\u0443 <a href=\"https:\/\/habr.com\/ru\/articles\/737548\/\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Yandex \u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f<\/a>. \u0412 \u043a\u043e\u043d\u0446\u0435 \u044d\u0442\u043e\u0439 \u0433\u043b\u0430\u0432\u044b, \u043c\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 introspection endpoint, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 Spring. \u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 DTO \u043a\u043b\u0430\u0441\u0441, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u043d\u0435\u0446 \u043c\u0435\u0442\u043e\u0434\u0430 <code>introspectionResponse()<\/code> \u0432 <code>AuthorizationServerConfig<\/code>. \u041c\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u0430 Jackson2 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b\u0438 \u043d\u0430\u0448 <code>TokenInfoDto<\/code> \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u0435\u0433\u043e \u0432 <code>HttpResponse<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/af3\/31d\/afc\/af331dafc951d34b46b875f1cc16992e.png\" alt=\"\u041c\u0435\u0442\u043e\u0434 introspectionResponse() \u043a\u043b\u0430\u0441\u0441\u0430 AuthorizationServerConfig\" title=\"\u041c\u0435\u0442\u043e\u0434 introspectionResponse() \u043a\u043b\u0430\u0441\u0441\u0430 AuthorizationServerConfig\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/af3\/31d\/afc\/af331dafc951d34b46b875f1cc16992e.png\"\/><\/p>\n<div><figcaption>\u041c\u0435\u0442\u043e\u0434 introspectionResponse() \u043a\u043b\u0430\u0441\u0441\u0430 AuthorizationServerConfig<\/figcaption><\/div>\n<\/figure>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>SpringOpaqueTokenIntrospector<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 Introspection endpoint \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 <code>j-service<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/698\/71f\/75b\/69871f75b1ac06437cca3e167af052d3.png\" alt=\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 claims \u0432 SpringOpaqueTokenIntrospector\" title=\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 claims \u0432 SpringOpaqueTokenIntrospector\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/698\/71f\/75b\/69871f75b1ac06437cca3e167af052d3.png\"\/><\/p>\n<div><figcaption>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 claims \u0432 SpringOpaqueTokenIntrospector<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <code>SpringOpaqueTokenIntrospector<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 <code>Map&lt;String, Object> claims<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 JSON \u0444\u043e\u0440\u043c\u0430\u0442 <code>TokenInfoDto<\/code>. \u0418 \u0442\u0443\u0442 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438, Jackson \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u0442\u0438\u043f <code>Instant<\/code> \u043d\u0435 \u0432 \u0447\u0438\u0441\u043b\u043e, \u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443. \u0421\u0440\u0430\u0437\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043f\u043e\u043b\u044f\u0445 <code>nbf<\/code>, <code>exp<\/code>, <code>iat<\/code> \u044d\u0442\u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e <strong>\u0441\u0435\u043a\u0443\u043d\u0434<\/strong> \u043e\u0442 \u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0440\u0435\u043c\u0451\u043d. \u042d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u0430\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@JsonFormat<\/code> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c Jackson-\u0443 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>Instant<\/code> \u0432 \u0447\u0438\u0441\u043b\u043e, \u043d\u043e \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b \u043a\u0430\u043a \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0438\u0436\u0435:<\/p>\n<p><code><strong>TokenInfoDto.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">public class TokenInfoDto {     \/\/ ....      @JsonFormat(             without = {JsonFormat.Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS},             shape = JsonFormat.Shape.NUMBER_INT     )     private Instant nbf;      \/\/ ..... } <\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043d\u0430\u043c \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u043d\u0435 \u0432\u0438\u0436\u0443 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 <code>JsonSerializer<\/code> \u0434\u043b\u044f \u0442\u0438\u043f\u0430 <code>Instant<\/code> \u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@JsonSerialize<\/code> \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430\u0434 \u043d\u0430\u0448\u0438\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u0448 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p><code><strong>JsonInstantSerializer.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">public class JsonInstantSerializer extends JsonSerializer&lt;Instant> {      @Override     public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {         if (value != null) {             gen.writeNumber(value.getEpochSecond());         } else {             gen.writeNull();         }     } } <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043d\u0430\u0434 \u043f\u043e\u043b\u044f\u043c\u0438 \u0441 \u0442\u0438\u043f\u043e\u043c Instant \u0432 <code>TokenInfoDto<\/code>:<\/p>\n<details class=\"spoiler\">\n<summary>TokenInfoDto.java<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\"> @Getter @Setter @Builder public class TokenInfoDto {      private Boolean active;     private String sub;     private List&lt;String> aud;     @JsonSerialize(using = JsonInstantSerializer.class)     private Instant nbf;     private List&lt;String> scopes;     private URL iss;     @JsonSerialize(using = JsonInstantSerializer.class)     private Instant exp;     @JsonSerialize(using = JsonInstantSerializer.class)     private Instant iat;     private String jti;     private String clientId;     private String tokenType;      private Object principal;     private Collection&lt;? extends GrantedAuthority> authorities; } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b. \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0435\u0449\u0451 \u0440\u0430\u0437 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 <code>j-service<\/code> \u0438 \u0432\u0443\u0430\u043b\u044f, \u0432\u0441\u0451 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e. \u0412 \u043e\u0442\u0432\u0435\u0442\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/7b1\/b22\/de0\/7b1b22de0f3ebd0818c2ef9d9612911d.png\" alt=\"\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 j-service\" title=\"\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 j-service\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/7b1\/b22\/de0\/7b1b22de0f3ebd0818c2ef9d9612911d.png\"\/><\/p>\n<div><figcaption>\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 j-service<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u043e \u043d\u0430 \u044d\u0442\u043e\u043c, \u043c\u044b \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u0441\u044f. \u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0449\u0451 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u0442\u043e\u043a\u0435\u043d\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 <code>j-service<\/code> \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u0435\u043a\u0442 <code>principal<\/code> \u0438\u0437 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432 <code>SecurityContext<\/code>. \u0412\u043e\u0442 \u0442\u0443\u0442 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u043e\u0435 \u0432\u0435\u0441\u0435\u043b\u044c\u0435.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0435\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 <a href=\"https:\/\/github.com\/spring-projects\/spring-security\/blob\/main\/oauth2\/oauth2-resource-server\/src\/main\/java\/org\/springframework\/security\/oauth2\/server\/resource\/introspection\/SpringOpaqueTokenIntrospector.java\" rel=\"noopener noreferrer nofollow\">Github \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Spring OAuth2 Resource Server \u043a\u043b\u0430\u0441\u0441 SpringOpaqueTokenIntrospector<\/a>.<\/p>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0441 \u043a\u0430\u043a\u043e\u0433\u043e-\u043d\u0438\u0431\u0443\u0434\u044c <code>AuthenticationProvider<\/code>. \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043d\u0430\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043c\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043c \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 &#8212; <code>OpaqueTokenAuthenticationProvider<\/code>, \u043f\u043e\u0445\u043e\u0436\u0435 \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/a34\/e25\/9a9\/a34e259a9b31a3f7e45d2f38521b01dc.png\" alt=\"OpaqueTokenAuthenticationProvider \u043c\u0435\u0442\u043e\u0434 authenticate()\" title=\"OpaqueTokenAuthenticationProvider \u043c\u0435\u0442\u043e\u0434 authenticate()\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/a34\/e25\/9a9\/a34e259a9b31a3f7e45d2f38521b01dc.png\"\/><\/p>\n<div><figcaption>OpaqueTokenAuthenticationProvider \u043c\u0435\u0442\u043e\u0434 authenticate()<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434 <code>authenticate()<\/code> \u0438 \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>OpaqueTokenIntrospector<\/code> \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <code>OAuth2AuthenticatedPrincipal<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f principal-\u043e\u043c \u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>Authentication<\/code>, \u043a\u043e\u0438\u043c \u0443 \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>BearerTokenAuthentication<\/code>. \u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u0430 <code>convert()<\/code> \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/623\/291\/e28\/623291e28f6b94eca083b5e3846c62fb.png\" alt=\"OpaqueTokenAuthenticationProvider \u043c\u0435\u0442\u043e\u0434 convert()\" title=\"OpaqueTokenAuthenticationProvider \u043c\u0435\u0442\u043e\u0434 convert()\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/623\/291\/e28\/623291e28f6b94eca083b5e3846c62fb.png\"\/><\/p>\n<div><figcaption>OpaqueTokenAuthenticationProvider \u043c\u0435\u0442\u043e\u0434 convert()<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435: \u0441\u043e\u0437\u0434\u0430\u0432 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>introspector<\/code> \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0432 \u0435\u0451 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f Principal \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438 \u043b\u044e\u0431\u043e\u0439 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041e\u043d \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>OAuth2AuthenticatedPrincipal<\/code>.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0442\u0430\u043a \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 DSL <code>oauth2ResourceServer<\/code>. \u0422\u0430\u043c \u043d\u0430\u0439\u0434\u0451\u043c \u043c\u0435\u0442\u043e\u0434 <code>opaqueToken<\/code> \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 <code>OpaqueTokenConfigurer<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/097\/04d\/4c0\/09704d4c04cf772aa024727315c255f7.png\" alt=\"\u041a\u043b\u0430\u0441\u0441 OpaqueTokenConfigurer\" title=\"\u041a\u043b\u0430\u0441\u0441 OpaqueTokenConfigurer\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/097\/04d\/4c0\/09704d4c04cf772aa024727315c255f7.png\"\/><\/p>\n<div><figcaption>\u041a\u043b\u0430\u0441\u0441 OpaqueTokenConfigurer<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 <code>OpaqueTokenIntrospector<\/code>. \u0410 \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>OpaqueTokenIntrospector<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 <code>j-sso<\/code> \u043d\u0430 introspection endpoint. \u0414\u0430\u043b\u0435\u0435, \u043f\u043e\u0439\u043c\u0451\u043c, \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0441\u043c\u0430\u043f\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435. \u0415\u0449\u0451 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>OAuth2AuthenticatedPrincipal<\/code>, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441 \u043d\u0443\u043b\u044f \u0432\u044b\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e  <code>OpaqueTokenIntrospector<\/code> \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u0440\u0443\u0434\u043e\u0451\u043c\u043a\u043e, \u0434\u0430 \u0438 \u0435\u0441\u043b\u0438 \u043f\u043e\u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u0435\u0439 \u0432\u0437\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u043d\u0430 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e (<code>SpringOpaqueTokenIntrospector<\/code>) \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u043d\u0435\u0439 \u0443\u0436\u0435 \u0432\u0441\u0451 \u0435\u0441\u0442\u044c. \u0422\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0447\u0443\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b: <code>introspect()<\/code> \u0438 <code>makeRequest()<\/code>. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0434\u0430\u043d\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043a\u0440\u044b\u0442\u0430 \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 OAuth2 Resource Server \u043d\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0436\u0438\u0437\u043d\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043d\u0430\u043c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f, \u043a\u0430\u043a \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>SpringOpaqueTokenIntrospector<\/code> \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u0435\u0451 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>CustomSpringTokenIntrospection<\/code>, \u0432 \u043d\u0435\u0433\u043e \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e  <code>SpringOpaqueTokenIntrospector<\/code>. \u0414\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 <code>RestTemplate<\/code> \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440 <code>MappingJackson2HttpMessageConverter<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p><code><strong>CustomSpringTokenIntrospection.java \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430<\/strong><\/code><\/p>\n<pre><code class=\"java\"> public class CustomSpringTokenIntrospection implements OpaqueTokenIntrospector {      private final RestOperations restOperations;     private Converter&lt;String, RequestEntity&lt;?>> requestEntityConverter;      public CustomSpringTokenIntrospection(String introspectionUri, String clientId, String clientSecret, MappingJackson2HttpMessageConverter jackson2HttpMessageConverter) {         Assert.notNull(introspectionUri, \"introspectionUri cannot be null\");         Assert.notNull(clientId, \"clientId cannot be null\");         Assert.notNull(clientSecret, \"clientSecret cannot be null\");         this.requestEntityConverter = this.defaultRequestEntityConverter(URI.create(introspectionUri));         RestTemplate restTemplate = new RestTemplate();         \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c jackson \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432         restTemplate.getMessageConverters().add(jackson2HttpMessageConverter);         restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(clientId, clientSecret));         this.restOperations = restTemplate;     }      \/\/ ....... }  <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 j-service <code>TokenInfoDto<\/code> \u0438\u0437 j-sso. \u041f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>makeRequest<\/code>, \u0442\u0430\u043a \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b \u0441\u0440\u0430\u0437\u0443 <code>TokenInfoDto<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p><code><strong>CustomSpringTokenIntrospection.java \u043c\u0435\u0442\u043e\u0434 makeRequest<\/strong><\/code><\/p>\n<pre><code class=\"java\">public class CustomSpringTokenIntrospection implements OpaqueTokenIntrospector {     \/\/ ......      private TokenInfoDto makeRequest(RequestEntity&lt;?> requestEntity) {         try {             return this.restOperations.postForObject(requestEntity.getUrl(), requestEntity, TokenInfoDto.class);         } catch (Exception ex) {             throw new OAuth2IntrospectionException(ex.getMessage(), ex);         }     }      \/\/ ...... } <\/code><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>introspect<\/code> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>OAuth2AuthenticatedPrincipal<\/code>. \u0422\u0430\u043a \u043a\u0430\u043a \u0434\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0432\u0438\u0434\u0435 <code>Map&lt;String, Object><\/code>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0433\u043e\u0440\u043e\u0434\u0438\u0442\u044c \u0433\u043e\u0440\u043e\u0434\u0443\u0448\u0435\u043a \u0438 \u0432 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0435 \u0443\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0430\u0436\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432, \u043c\u044b, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c <code>OAuth2TokenIntrospectionClaimAccessor<\/code>, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>TokenInfoOAuth2ClaimAccessor<\/code> \u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0432 \u043d\u0451\u043c \u0432\u0441\u0435 \u0433\u0435\u0442\u0442\u0435\u0440\u044b.<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>TokenInfoOAuth2ClaimAccessor.java<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">public abstract class TokenInfoOAuth2ClaimAccessor implements OAuth2TokenIntrospectionClaimAccessor {      @Override     public Map&lt;String, Object> getClaims() {         return null;     }      \/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 TokenInfoDto     abstract TokenInfoDto getTokenInfo();      @Override     public boolean isActive() {         return this.getTokenInfo().getActive();     }      @Override     public String getUsername() {         return this.getTokenInfo().getSub();     }      @Override     public String getClientId() {         return this.getTokenInfo().getClientId();     }      @Override     public List&lt;String> getScopes() {         return this.getTokenInfo().getScopes();     }      @Override     public String getTokenType() {         return this.getTokenInfo().getTokenType();     }      @Override     public Instant getExpiresAt() {         return this.getTokenInfo().getExp();     }      @Override     public Instant getIssuedAt() {         return this.getTokenInfo().getIat();     }      @Override     public Instant getNotBefore() {         return this.getTokenInfo().getNbf();     }      @Override     public String getSubject() {         return this.getTokenInfo().getSub();     }      @Override     public List&lt;String> getAudience() {         return this.getTokenInfo().getAud();     }      @Override     public URL getIssuer() {         return this.getTokenInfo().getIss();     }      @Override     public String getId() {         return this.getTokenInfo().getJti();     } }  <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <code>CustomOAuth2AuthenticatedPrincipal<\/code> (\u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u0438\u0436\u0435). \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u043e\u043b\u0435 <code>delegate<\/code>, \u043e\u043d\u043e \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f <code>AuthorizedUser<\/code> &#8212; \u044d\u0442\u043e \u0442\u043e\u0442 \u0436\u0435 <code>AuthorizedUser<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 <code>j-sso<\/code> \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u043b\u0435 principal <code>TokenInfoDto<\/code>.<\/p>\n<p><code><strong>CustomOAuth2AuthenticatedPrincipal.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">public class CustomOAuth2AuthenticatedPrincipal extends TokenInfoOAuth2ClaimAccessor implements OAuth2AuthenticatedPrincipal, Serializable {      private final AuthorizedUser delegate;     private final TokenInfoDto tokenInfo;      public CustomOAuth2AuthenticatedPrincipal(TokenInfoDto tokenInfo) {         \/\/ tokenInfo.getPrincipal() - \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 access \u0442\u043e\u043a\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u043f\u0443\u0442\u0435\u043c grant_type=client_credentials         this.delegate = AuthorizedUser.build(tokenInfo.getPrincipal());         this.tokenInfo = tokenInfo;     }      public Map&lt;String, Object> getAttributes() {         return Collections.emptyMap();     }      public Collection&lt;? extends GrantedAuthority> getAuthorities() {         if (this.delegate == null) {             return Collections.emptyList();         }         return this.delegate.getAuthorities();     }      \/**      * \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0432\u043d\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (Client Credential Grant Type), \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c client_id      *\/     public String getName() {         if (this.delegate == null) {             return this.tokenInfo.getClientId();         }         return this.delegate.getName();     }      @Override     TokenInfoDto getTokenInfo() {         return this.tokenInfo;     } } <\/code><\/pre>\n<ol start=\"5\">\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>introspect<\/code>. \u0423\u0447\u0442\u0451\u043c, \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u0438 \u043c\u0435\u0442\u043e\u0434 <code>makeRequest<\/code> \u0438 \u0447\u0442\u043e \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c <code>CustomOAuth2AuthenticatedPrincipal<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p><code><strong>CustomSpringTokenIntrospection.java \u043c\u0435\u0442\u043e\u0434 introspect<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j public class CustomSpringTokenIntrospection implements OpaqueTokenIntrospector {      private final RestOperations restOperations;     private Converter&lt;String, RequestEntity&lt;?>> requestEntityConverter;      \/\/ .....      public OAuth2AuthenticatedPrincipal introspect(String token) {         RequestEntity&lt;?> requestEntity = this.requestEntityConverter.convert(token);         if (requestEntity == null) {             throw new OAuth2IntrospectionException(\"requestEntityConverter returned a null entity\");         } else {             TokenInfoDto tokenInfo = this.makeRequest(requestEntity);             if (!tokenInfo.getActive()) {                 log.trace(\"Did not validate token since it is inactive\");                 throw new BadOpaqueTokenException(\"Provided token isn't active\");             }             return new CustomOAuth2AuthenticatedPrincipal(tokenInfo);         }     }      \/\/ ......      private TokenInfoDto makeRequest(RequestEntity&lt;?> requestEntity) {         try {             return this.restOperations.postForObject(requestEntity.getUrl(), requestEntity, TokenInfoDto.class);         } catch (Exception ex) {             throw new OAuth2IntrospectionException(ex.getMessage(), ex);         }     } } <\/code><\/pre>\n<p>\u0412\u0435\u0441\u044c \u043a\u043e\u0434, \u043a\u043b\u0430\u0441\u0441\u0430 <code>CustomSpringTokenIntrospection<\/code> \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-2.1\/j-service\/src\/main\/java\/ru\/dlabs\/sas\/example\/jservice\/config\/introspector\/CustomSpringTokenIntrospection.java\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 introspector \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u043d\u0430\u043c ResourceConfig \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<p><code><strong>ResourceServerConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Configuration @EnableWebSecurity(debug = true) @RequiredArgsConstructor public class ResourceServerConfig {      private final OAuth2ResourceOpaqueProperties resourceProperties;     private final MappingJackson2HttpMessageConverter messageConverter;      @Bean     public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {         \/\/ \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u0435\u0441\u0441\u0438\u0439         http.sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))                 .authorizeHttpRequests(customizer -> {                     customizer.anyRequest().authenticated();                 });          \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 OAuth2 Resource Server \u0441 Opaque Token.         \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 introspector \u043d\u0430\u0448\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e         http.oauth2ResourceServer(configurer -> {             configurer.opaqueToken(customizer -> {                 customizer.introspector(new CustomSpringTokenIntrospection(                         resourceProperties.getIntrospectionUri(),                         resourceProperties.getClientId(),                         resourceProperties.getClientSecret(),                         messageConverter                 ));             });         });         return http.build();     } } <\/code><\/pre>\n<p>\u041c\u043d\u0435 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-2.1\/j-service\/src\/main\/java\/ru\/dlabs\/sas\/example\/jservice\/config\/OAuth2ResourceOpaqueProperties.java\" rel=\"noopener noreferrer nofollow\"><code>OAuth2ResourceOpaqueProperties<\/code><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a resource server. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u0445 \u0438\u0437 <code>OpaqueTokenConfigurer<\/code> \u044f \u043d\u0435 \u043d\u0430\u0448\u0451\u043b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0448\u0451\u043b \u044d\u0442\u0438\u043c \u043f\u0443\u0442\u0451\u043c.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u043d\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u043c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 <code>TokenInfoDto<\/code>, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u043f\u043e\u043b\u044f <code>principal<\/code> \u0438 <code>authorities<\/code>.<\/p>\n<p><code><strong>TokenInfoDto.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter @Builder public class TokenInfoDto {      \/\/ ....      private Object principal;     private Collection&lt;? extends GrantedAuthority> authorities; } <\/code><\/pre>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u0438\u043f <code>Object<\/code> \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0432\u043b\u0435\u0447\u044c \u0437\u0430 \u0441\u043e\u0431\u043e\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u0430\u0433\u043e\u0432 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c. \u0422\u0430\u043a\u0436\u0435, \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 <code>principal<\/code> \u0438\u0442\u0430\u043a \u0443\u0436\u0435 \u0435\u0441\u0442\u044c <code>authorities<\/code>, \u043d\u0435\u0437\u0430\u0447\u0435\u043c \u0442\u043e\u0433\u0434\u0430 \u043d\u0430\u043c \u0438\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0432\u0430\u0436\u0434\u044b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u044f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e, \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>IntrospectionPrincipal<\/code> \u0438 \u043f\u0443\u0441\u0442\u044c \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 introspection endpoint. \u0421\u0442\u043e\u0438\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u043d\u0435 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e <code>AuthorizedUser<\/code>. \u042d\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441-DTO, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u0418 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430 <code>AuthorizedUser<\/code>.<\/p>\n<p><code><strong>IntrospectionPrincipal.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class IntrospectionPrincipal {      private UUID id;     private String firstName;     private String secondName;     private String middleName;     private LocalDate birthday;     private String avatarUrl;     private String username;     private String email;     private Collection&lt;? extends GrantedAuthority> authorities; } <\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u043b\u0435 <code>authorities<\/code> \u0438\u0437 <code>TokenInfoDto<\/code> \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0438\u043f \u0443 \u043f\u043e\u043b\u044f <code>principal<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>TokenInfoDto.java<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\"> @Getter @Setter @NoArgsConstructor public class TokenInfoDto {      private Boolean active;     private String sub;     private List&lt;String> aud;     private Instant nbf;     private List&lt;String> scopes;     private URL iss;     private Instant exp;     private Instant iat;     private String jti;     private String clientId;     private String tokenType;      private IntrospectionPrincipal principal; } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u042d\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u0430\u043a \u0432 <code>j-sso<\/code>, \u0442\u0430\u043a \u0438 \u0432 <code>j-services<\/code>. \u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043c\u043e\u0434\u0443\u043b\u044c <code>introspection-api<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 DTO \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043a \u043e\u0431\u043e\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c. \u0414\u0430\u043b\u0435\u0435, \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>introspectionResponse<\/code> \u0432 <code>AuthorizationServerConfig<\/code> \u043c\u043e\u0434\u0443\u043b\u044f <code>j-sso<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>AuthorizationServerConfig.java \u043c\u0435\u0442\u043e\u0434 introspectionResponse<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\"> @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class AuthorizationServerConfig {     \/\/ ....      private void introspectionResponse(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {         OAuth2TokenIntrospectionAuthenticationToken introspectionAuthenticationToken = (OAuth2TokenIntrospectionAuthenticationToken) authentication;         TokenInfoDto.TokenInfoDtoBuilder tokenInfoDtoBuilder = TokenInfoDto.builder().active(false);                        \/\/ \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0431\u0438\u043b\u0434\u0435\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043e\u0442\u0432\u0435\u0442\u0430         if (introspectionAuthenticationToken.getTokenClaims().isActive()) {                                                 \/\/ \u0435\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0430\u043a\u0442\u0438\u0432\u0435\u043d, \u0442\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0438 \u0434\u0430\u043b\u0435\u0435 \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435             OAuth2TokenIntrospection claims = introspectionAuthenticationToken.getTokenClaims();             tokenInfoDtoBuilder.active(true)                     .sub(claims.getSubject())                     .aud(claims.getAudience())                     .nbf(claims.getNotBefore())                     .scopes(claims.getScopes())                     .iss(claims.getIssuer())                     .exp(claims.getExpiresAt())                     .iat(claims.getIssuedAt())                     .jti(claims.getId())                     .clientId(claims.getClientId())                     .tokenType(claims.getTokenType());              \/\/ \u0417\u0434\u0435\u0441\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f             String token = introspectionAuthenticationToken.getToken();                                                      \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f             OAuth2Authorization tokenAuth = oAuth2AuthorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN);     \/\/ \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u044f \u0447\u0442\u043e \u044d\u0442\u043e ACCESS TOKEN, \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 OAuth2Authorization \u0438\u0437 OAuth2AuthorizationService             if (tokenAuth != null) {                 Authentication attributeAuth = tokenAuth.getAttribute(principalAttributeKey);                                \/\/ \u0415\u0441\u043b\u0438 \u043d\u0430\u0439\u0434\u0435\u043d \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 OAuth2Authorization, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0437 \u043d\u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442 Authentication \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c                 if (attributeAuth != null) {                     if (attributeAuth.getPrincipal() instanceof AuthorizedUser authorizedUser) {                             \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 Authentication \u043d\u0435 \u043f\u0443\u0441\u0442, \u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0435\u0433\u043e principal \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0430 AuthorizedUser                         tokenInfoDtoBuilder.principal(IntrospectionPrincipal.build(authorizedUser));                         \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c IntrospectionPrincipal \u043d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435                     } else {                                                                                                 \/\/ \u0418\u043d\u0430\u0447\u0435 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u0442\u0438\u043f\u044b principal \u043c\u044b \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c                         throw new RuntimeException(\"Principal class = \" + attributeAuth.getPrincipal().getClass().getSimpleName() + \" is not supported\");                     }                 }             }         }          ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);         mappingJackson2HttpMessageConverter.write(tokenInfoDtoBuilder.build(), null, httpResponse);              \/\/ \u041f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430\u0448 TokenInfoDto \u0432 json \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0451 \u0447\u0435\u0440\u0435\u0437 ServletServerHttpResponse     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u0441\u0451, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0442\u043e\u0447\u043d\u043e \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c <code>SecurityContext<\/code> \u0432 <code>j-service<\/code>. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c access \u0442\u043e\u043a\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0432\u043d\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (\u0442.\u0435. Client Credential Grant Type). \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e Vue\/JS \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (\u043c\u043e\u0434\u0443\u043b\u044c <code>test-client<\/code>), \u043c\u044b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u043c\u0441\u044f \u043f\u043e\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c <code>admin@example.com<\/code> \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c access \u0442\u043e\u043a\u0435\u043d. \u0414\u0430\u043b\u0435\u0435, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043a <code>j-service<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/114\/335\/156\/1143351566a685d28e4a8c963af4a4c0.png\" alt=\"\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a j-service\" title=\"\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a j-service\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/114\/335\/156\/1143351566a685d28e4a8c963af4a4c0.png\"\/><\/p>\n<div><figcaption>\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a j-service<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0442\u043e\u0447\u043a\u0443 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0430 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 <code>j-service<\/code>, \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 <code>SecurityContext<\/code>. \u0412\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 <code>Authentication<\/code> \u0438\u043c\u0435\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>BearerTokenAuthentication<\/code>, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0435\u0441\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 principal, \u0438\u043c\u0435\u044e\u0449\u0438\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>CustomOAuth2AuthenticatedPrincipal<\/code>. \u0410 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0433\u043e \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 <code>delegate<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 <code>AuthorizedUser<\/code>. \u042f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0441\u0442\u0430\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 principal \u0432 <code>BearerTokenAuthentication<\/code> \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0438\u043f\u043e\u043c <code>AuthorizedUser<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441, \u043f\u043e\u043c\u0438\u043c\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435, \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u043c \u044d\u0442\u043e\u0442 \u0442\u043e\u043a\u0435\u043d. \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0438\u0437-\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0445 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 principal, \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>CustomOAuth2AuthenticatedPrincipal<\/code>, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 <code>CustomOAuth2AuthenticatedPrincipal<\/code> \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0432 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u044f \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u043a\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c \u043d\u0430\u0448 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 introspection endpoint \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 OAuth2 Resource Server \u0432 Spring.<\/p>\n<blockquote>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.1\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 2.2: \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c PostgreSQL \u0438 \u0440\u0430\u0441\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0441\u0445\u0435\u043c\u0443 \u0411\u0414<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043d\u0430\u0447\u043d\u0451\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e &#171;\u043f\u0440\u043e\u043a\u0430\u0447\u0430\u0442\u044c&#187; \u043d\u0430\u0448 \u0441\u043b\u043e\u0439 DAO (\u0441\u043b\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438) \u043c\u043e\u0434\u0443\u043b\u044f <code>j-sso<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u043c \u0433\u0434\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u043a\u0430\u043a \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u044d\u0442\u0438\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0442\u0432\u0435\u0442 \u043e\u0447\u0435\u0432\u0438\u0434\u0435\u043d, \u043c\u044b \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f PostgreSQL. \u0410 \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f Spring.<\/p>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0433\u0434\u0435-\u0442\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c PostgreSQL. \u0414\u043b\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441\u0440\u0435\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430\u043c \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 docker \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441 \u0421\u0423\u0411\u0414. \u041d\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u043c \u0431\u044b\u043b\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u0443\u0434\u043e\u0431\u043d\u043e, \u043c\u044b \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c docker-compose. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <code>docker-compose.yml<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441 <code>j-postgres<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438 \u0431\u0443\u0434\u0435\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0435\u0439 \u0421\u0423\u0411\u0414. \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043f\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c \u0434\u0430\u043d\u043d\u043e\u0433\u043e image \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 <a href=\"https:\/\/hub.docker.com\/_\/postgres\" rel=\"noopener noreferrer nofollow\">Docker Hub<\/a><\/p>\n<p><strong>docker-compose.yml<\/strong><\/p>\n<pre><code class=\"yaml\">version: '3.3' services:   j-postgres:     image: postgres:15.3     container_name: j-postgres     ports:       - '5435:5432'     environment:       POSTGRES_PASSWORD: \"user\"       POSTGRES_USER: \"user\"       POSTGRES_DB: \"j-sso\"     restart: always     volumes:       - .\/docker\/postgres\/data:\/var\/lib\/postgresql\/data     networks:       - j-network  networks:   j-network:     ipam:       driver: default       config:         - subnet: \"14.205.210.0\/24\" <\/code><\/pre>\n<p>\u0410 \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u0430\u043a\u0438\u0445 \u043b\u0438\u0431\u043e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e docker networks. \u0412 \u043d\u0435\u0439 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e \u043f\u043e\u0434\u0441\u0435\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u043e\u0438\u0445 \u0434\u043e\u043a\u0435\u0440 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432. \u0412\u044b \u0435\u0451 \u0441\u043c\u0435\u043b\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u043d\u0443\u0436\u0434\u044b. \u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451, \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c PostgreSQL \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f. \u0414\u0430\u043b\u0435\u0435, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0447\u0430\u0441\u0442\u0438 Spring.<\/p>\n<h4>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a \u0421\u0423\u0411\u0414<\/h4>\n<p>Spring \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043f\u043e\u0434-\u043f\u0440\u043e\u0435\u043a\u0442 Spring Data, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0430\u043a \u0440\u0430\u0437 \u0438 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0418\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <a href=\"https:\/\/spring.io\/projects\/spring-data\" rel=\"noopener noreferrer nofollow\">Spring Data<\/a><\/p>\n<blockquote>\n<p>Spring Data\u2019s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store.<\/p>\n<\/blockquote>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0430\u043c \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u0438 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 <a href=\"https:\/\/spring.io\/projects\/spring-data-jpa\" rel=\"noopener noreferrer nofollow\">Spring Data JPA<\/a>. \u0423 \u043d\u0438\u0445 \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/spring.io\/guides\/gs\/accessing-data-jpa\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u0445 \u0433\u0430\u0439\u0434<\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443. \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 <code>pom.xml<\/code> \u043d\u0430\u0448\u0435\u0433\u043e <code>j-sso<\/code>.<\/p>\n<ol>\n<li>\n<p><code>spring-boot-starter-data-jpa<\/code> &#8212; \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 <code>spring-data-jpa<\/code>, <code>hibernate<\/code>, <code>HikariCP<\/code> \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b<\/p>\n<\/li>\n<li>\n<p><code>postgresql<\/code> &#8212; JDBC \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a PostgreSQL.<\/p>\n<\/li>\n<\/ol>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ ....      &lt;dependencies>         \/\/ ....          &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-starter-data-jpa&lt;\/artifactId>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.postgresql&lt;\/groupId>             &lt;artifactId>postgresql&lt;\/artifactId>         &lt;\/dependency>          \/\/ ....     &lt;\/dependencies> &lt;\/project> <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043d\u0438\u0436\u0435\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432 \u043d\u0430\u0448 <code>application.yml<\/code> \u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a PostgreSQL \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e.<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">\/\/ .....  spring:   application:     name: j-sso   datasource:     url: \"jdbc:postgresql:\/\/localhost:5435\/j-sso\" \/\/ URL \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0411\u0414     username: \"user\"                              \/\/ \u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0421\u0423\u0411\u0414     password: \"user\"                              \/\/ \u041f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0421\u0423\u0411\u0414     driver-class-name: \"org.postgresql.Driver\"    \/\/ \u043f\u0443\u0442\u044c \u0434\u043e \u043a\u043b\u0430\u0441\u0441\u0430 JDBC \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 (\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0432\u044b\u0448\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0432\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c)     hikari:                                       \/\/ \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0443\u043b\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 (HikariCP)       connection-timeout: 30000       maximum-pool-size: 10       minimum-idle: 10       initialization-fail-timeout: 1       leak-detection-threshold: 0       pool-name: \"HikariPool-j-sso\"       register-mbeans: true    \/\/ ..... <\/code><\/pre>\n<p>\u041d\u0435 \u0441\u043c\u043e\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0432\u044b\u0441\u043e\u043a\u043e-\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 &#171;\u0442\u044e\u043d\u0438\u0442\u044c&#187; \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0443\u043b\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043e\u0441\u043e\u0431\u043e \u043d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430, \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c (\u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432\u044b\u0440\u0430\u0441\u0442\u0430\u0435\u0442 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442) \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0443\u043b\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043f\u0440\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0445 \u0441 \u043d\u0438\u043c. \u0422\u0430\u043a\u0436\u0435, \u044d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0432 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0438 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0443\u043b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0438 \u043a\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0445 \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0431\u044b\u0441\u0442\u0440\u0435\u043d\u044c\u043a\u043e \u043f\u0440\u043e\u0431\u0435\u0436\u0438\u043c\u0441\u044f \u043f\u043e \u0434\u0430\u043d\u043d\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c:<\/p>\n<ol>\n<li>\n<p><code>connection-timeout<\/code> &#8212; \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434, \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u043f\u0443\u043b\u0430.<\/p>\n<\/li>\n<li>\n<p><code>maximum-pool-size<\/code> &#8212; \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0443\u043b\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><code>minimum-idle<\/code> &#8212; \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u0438\u0432\u0430\u044e\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 HikariCP \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0432 \u043f\u0443\u043b\u0435. \u041d\u043e \u0434\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0432\u043e\u0437\u0440\u043e\u0441\u0448\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0441\u043e\u0432\u0435\u0442\u0443\u044e\u0442 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0432\u043d\u043e\u0435 <code>maximum-pool-size<\/code>, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0434\u0435\u043b\u0430\u044f \u043f\u0443\u043b \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0440\u0430\u0432\u0435\u043d <code>maximum-pool-size<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>initialization-fail-timeout<\/code> &#8212; \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435. \u042d\u0442\u043e\u0442 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 <code>connection-timeout<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>leak-detection-threshold<\/code> &#8212; \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434, \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043d\u0435 \u043f\u0443\u043b\u0430, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0435 \u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0443\u044e \u0443\u0442\u0435\u0447\u043a\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><code>pool-name<\/code> &#8212; \u0438\u043c\u044f \u043f\u0443\u043b\u0430. \u0423\u0434\u043e\u0431\u043d\u043e \u043f\u043e\u0442\u043e\u043c \u043b\u043e\u0433\u0438 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c<\/p>\n<\/li>\n<li>\n<p><code>register-mbeans<\/code> &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f JMX (MBeans). \u042d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043b\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0438 \u0441\u0431\u043e\u0440\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438, \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 \u043f\u0440\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u0445. <a href=\"https:\/\/github.com\/brettwooldridge\/HikariCP\/wiki\/MBean-(JMX)-Monitoring-and-Management\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<\/ol>\n<p>\u042d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0443\u043b\u0430, \u043d\u043e HikariCP \u0438\u043c\u0435\u0435\u0442 \u0435\u0449\u0451 \u043a\u0443\u0447\u0443 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/brettwooldridge\/HikariCP#gear-configuration-knobs-baby\" rel=\"noopener noreferrer nofollow\">\u0438\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0430 Github<\/a>.<\/p>\n<p>\u041f\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043d\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u044f\u0442, \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u0435\u0449\u0451 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@EnableJpaRepositories<\/code>. \u041f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u043d\u0435\u0439 \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435. \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 <code>j-sso<\/code> \u0438 \u0443\u0432\u0438\u0434\u0438\u043c \u0432 \u043b\u043e\u0433\u0430\u0445 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u043e\u0441\u044c.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/625\/188\/3a0\/6251883a064fe8fb5b0f05936ceed5fe.png\" alt=\"\u041b\u043e\u0433\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 j-sso\" title=\"\u041b\u043e\u0433\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 j-sso\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/625\/188\/3a0\/6251883a064fe8fb5b0f05936ceed5fe.png\"\/><\/p>\n<div><figcaption>\u041b\u043e\u0433\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 j-sso<\/figcaption><\/div>\n<\/figure>\n<p>\u0418\u0442\u0430\u043a, \u0411\u0414 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u043d\u0435\u0439 \u0442\u043e\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e. \u0422\u0435\u043f\u0435\u0440\u044c, \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0442\u043e\u043c, \u0433\u0434\u0435 \u0438 \u043a\u0430\u043a \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c\u044b \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043a\u0430\u043a \u0438\u043c\u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<h4>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 DDL \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438<\/h4>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0430\u043a\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441\u0445\u0435\u043c\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u0434\u043d\u0430 \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 &#8212; <strong>Liquibase<\/strong>. \u042f \u0437\u043d\u0430\u043a\u043e\u043c \u0441 \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u043e\u0447\u0435\u043d\u044c \u0434\u0430\u0432\u043d\u043e, \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0435\u0451 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e. \u041e\u043d\u0430 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 \u0432\u0441\u0435 \u043c\u043e\u0438 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0440\u0430\u0431\u043e\u0442\u0435 \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 \u0411\u0414, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043c\u0438 Spring Boot. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0451.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c:<\/p>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">     \/\/ ....     &lt;dependencies>         \/\/ ....         &lt;dependency>             &lt;groupId>org.liquibase&lt;\/groupId>             &lt;artifactId>liquibase-core&lt;\/artifactId>         &lt;\/dependency>         \/\/ ....     &lt;\/dependencies> &lt;\/project> <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0441\u043b\u0435\u0433\u043a\u0430 \u043e\u0442\u0432\u043b\u0435\u0447\u0451\u043c\u0441\u044f \u043e\u0442 \u043a\u043e\u0434\u0430 \u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0441\u0445\u0435\u043c\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u0430\u043d\u043d\u044b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043c\u044b \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>database<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u0440\u043d\u0435 \u043c\u043e\u0434\u0443\u043b\u044f <code>j-sso<\/code>. \u0412 \u043d\u0435\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0451, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e \u0441 liquibase. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u044d\u0442\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/4cd\/b4a\/79f\/4cdb4a79faf265a31bf92a369e9b50b3.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 database\" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 database\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/4cd\/b4a\/79f\/4cdb4a79faf265a31bf92a369e9b50b3.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 database<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f 3 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<ol>\n<li>\n<p><code>extensions.sql<\/code> &#8212; \u0432 \u044d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f change-set-\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0421\u0423\u0411\u0414<\/p>\n<\/li>\n<li>\n<p><code>schemas.sql<\/code> &#8212; \u0432 \u044d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f change-set-\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c \u0411\u0414<\/p>\n<\/li>\n<li>\n<p><code>db.changelog.yaml<\/code> &#8212; \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0444\u0430\u0439\u043b changelog \u0434\u043b\u044f liquibase. \u0412 \u043d\u0451\u043c \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 <code>schemas.sql<\/code> \u0438 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0440\u0435\u043b\u0438\u0437\u043e\u0432. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430<\/p>\n<\/li>\n<li>\n<p>\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>release-&lt;\u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f><\/code> &#8212; \u0432 \u044d\u0442\u0438\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0445 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432\u0441\u0435 change-set-\u044b \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u043d\u0438 \u0442\u043e\u0436\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.<\/p>\n<\/li>\n<\/ol>\n<p><code><strong>db.changelog.yaml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">databaseChangeLog:   - include:       file: extensions.sql       relativeToChangelogFile: true   - include:       file: schemas.sql       relativeToChangelogFile: true   - include:       file: release-1.0.0\/release.changelog.yaml       relativeToChangelogFile: true <\/code><\/pre>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 <code>release-*<\/code> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u0424\u0430\u0439\u043b <code>release.changelog.yaml<\/code> &#8212; \u043e\u043d \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 <code>.sql<\/code> \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437 \u043d\u0438\u0436\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439. \u0418\u043c\u0435\u043d\u043d\u043e \u043e\u043d \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 changelog \u0444\u0430\u0439\u043b. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043d\u0438\u0436\u0435.<\/p>\n<\/li>\n<\/ol>\n<p><code><strong>release.changelog.yaml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">databaseChangeLog:   #  Objects   - include:       file: object\/users.sql       relativeToChangelogFile: true       contextFilter: prod   - include:       file: object\/system-oauth2-clients.sql       relativeToChangelogFile: true       contextFilter: prod    #  Data   - include:       file: data\/system-oauth2-clients-data.sql       relativeToChangelogFile: true       contextFilter: prod    # Data dev   - include:       file: data\/dev\/users-data.sql       relativeToChangelogFile: true       contextFilter: dev <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>object<\/code> &#8212; \u0432 \u043d\u0435\u0439 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u0441\u0435 <code>.sql<\/code> \u0444\u0430\u0439\u043b\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0441 DDL \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0438 \u0442.\u0434.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>data<\/code> &#8212; \u0432 \u043d\u0435\u0439 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u0441\u0435 <code>.sql<\/code> \u0444\u0430\u0439\u043b\u044b \u0441 DML \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0431\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>data<\/code> \u0435\u0441\u0442\u044c \u043f\u043e\u0434-\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>dev<\/code> &#8212; \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u044d\u0442\u0438\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u043a\u0430\u0442 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0438\u0437\u043d\u0435\u0441 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u0442.\u0434. \u0422\u0430\u043a\u0443\u044e \u0436\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u0432 <code>object<\/code>, \u043d\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0440\u0435\u0434\u043a\u0438\u0435 \u0441\u043b\u0443\u0447\u0430\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043d\u0435 \u0441\u0442\u0430\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0435\u0451.<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>contextFilter<\/code> \u0432 changelog \u0444\u0430\u0439\u043b\u0430\u0445. \u0418\u043c\u0435\u043d\u043d\u043e \u0438\u043c \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430 \u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0423 \u0432\u0430\u0441, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u0440\u0430\u0437\u0443 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c changelog \u0444\u0430\u0439\u043b\u044b \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0445 <code>object<\/code> \u0438 <code>data<\/code>, \u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043d\u0430\u0434\u043e. \u041f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0438\u043d\u043e\u0439 \u0440\u0430\u0437 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0430 \u043f\u043e\u0442\u043e\u043c \u0441\u043e \u0441\u0445\u0435\u043c\u043e\u0439. \u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u044d\u0442\u043e \u043c\u0430\u043b\u043e\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f, \u043d\u043e \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u043b\u0438\u0437\u0430\u0445, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u044d\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0430\u0449\u0435. \u0422\u0430\u043a\u0436\u0435, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>data<\/code> \u0438 <code>object<\/code>, \u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u0443\u0436\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0440\u0435\u043b\u0438\u0437\u043e\u0432 (<code>release-*<\/code>), \u0442\u0430\u043a \u0442\u043e\u0436\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0441\u0442\u043e\u0438\u0442. \u0412\u0441\u0451 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u043d\u0430\u0447\u043d\u0451\u0442\u0435 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430\u043a\u0430\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0451\u0442\u0435\u0441\u044c \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c DML \u0441\u043a\u0440\u0438\u043f\u0442\u044b. \u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0432\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0441\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0435 DDL \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0432\u0430\u0448\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0430. \u0417\u0430\u0442\u0435\u043c \u0438\u0437 \u043d\u0435\u0451 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0430. \u0410 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c DML \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430\u043a\u0430\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443. \u0418\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u043d\u043e \u044d\u0442\u043e \u043f\u043b\u043e\u0445\u043e\u0439 \u0442\u043e\u043d \u0438 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u043f\u0440\u0438 \u0440\u0430\u0441\u043a\u0430\u0442\u0435 \u043d\u0430 \u043f\u0440\u043e\u0434\u0435. \u042d\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0432 Liquibase \u0435\u0441\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u0438\u0435 hashSum changeSet-\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 hash \u0441\u0443\u043c\u043c\u0443 sql \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0418 \u0435\u0441\u043b\u0438 \u0432\u044b \u0435\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u0442\u0435, \u0442\u043e Liquibase \u0431\u0443\u0434\u0435\u0442 &#171;\u0440\u0443\u0433\u0430\u0442\u044c\u0441\u044f&#187;.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0441\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446 <code>sso.users<\/code> \u0438 <code>sso.system_oauth2_clients<\/code>, \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c DML \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430\u043a\u0430\u0442\u0430 <code>test-client<\/code> \u0438 \u0432 dev-\u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c INSERT \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 email <code>example@example.ru<\/code>. \u0412\u0441\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u0445 \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.2\/j-sso\/database\/release-1.0.0\/object\" rel=\"noopener noreferrer nofollow\">Github \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043f\u0430\u0440\u043e\u043b\u0438 \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0445\u044d\u0448 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e BCrypt \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c round = 10 (\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e). \u0414\u043b\u044f \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u0435\u0439, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c <code>Blowfish<\/code>, \u0430 bcrypt \u043a\u0430\u043a \u0440\u0430\u0437 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0448\u0438\u0444\u0440\u0435 <code>Blowfish<\/code>. \u041d\u0438\u0436\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c <code>PasswordEncoder<\/code> \u0432 \u043d\u0430\u0448\u0435\u043c <code>j-sso<\/code>.<\/p>\n<blockquote>\n<p>bcrypt \u2014 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u0430\u044f \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0445\u0435\u0448-\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u0434\u043b\u044f \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u0435\u0439. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438: \u041d\u0438\u043b\u044c\u0441 \u041f\u0440\u043e\u0432\u043e\u0441 \u0438 David Mazi\u00e8res. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u0448\u0438\u0444\u0440\u0435 Blowfish, \u0432\u043f\u0435\u0440\u0432\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043d\u0430 USENIX \u0432 1999 \u0433\u043e\u0434\u0443.<\/p>\n<\/blockquote>\n<h4>\u0417\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u043a\u0430\u0442\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b Liquibase, \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043d\u0430\u043a\u0430\u0442\u0430. \u0415\u0441\u0442\u044c \u0434\u0432\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0438 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043e\u0431\u0430:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430\u043a\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043a\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/docs.liquibase.com\/tools-integrations\/maven\/getting-started-liquibase-maven.html\" rel=\"noopener noreferrer nofollow\">liquibase-maven-plugin<\/a><\/p>\n<\/li>\n<\/ol>\n<h3>\u041d\u0430\u043a\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u043a\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>database<\/code> \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0441\u0431\u043e\u0440\u043a\u0438 (\u0442.\u0435. \u0432 <code>target\/classes<\/code>). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>database<\/code> \u043a\u0430\u043a \u0440\u0435\u0441\u0443\u0440\u0441 \u0432 <code>pom.xml<\/code>.<\/p>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ .....      &lt;build>         &lt;finalName>${project.artifactId}&lt;\/finalName>         &lt;plugins>             &lt;plugin>                 &lt;groupId>org.springframework.boot&lt;\/groupId>                 &lt;artifactId>spring-boot-maven-plugin&lt;\/artifactId>                 &lt;configuration>                     &lt;finalName>${project.name}&lt;\/finalName>                 &lt;\/configuration>             &lt;\/plugin>         &lt;\/plugins>          &lt;resources>             &lt;!-- \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0448\u0443 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e database \u0432 \u0441\u0431\u043e\u0440\u043a\u0443-->             &lt;resource>                 &lt;directory>${project.basedir}\/database&lt;\/directory>                 &lt;targetPath>${project.build.directory}\/classes\/database&lt;\/targetPath>             &lt;\/resource>             &lt;resource>                 &lt;directory>${project.basedir}\/src\/main\/resources&lt;\/directory>             &lt;\/resource>         &lt;\/resources>     &lt;\/build>  &lt;\/project> <\/code><\/pre>\n<p>\u0410 \u0434\u0430\u043b\u0435\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Liquibase \u0432 <code>application.yml<\/code>. \u041c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0432\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 <code>dev<\/code> \u0438 <code>prod<\/code>, \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u043a\u0430\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e <code>prod<\/code> \u0434\u043b\u044f \u0440\u0430\u0441\u043a\u0430\u0442\u0430, \u0431\u0435\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041a\u0430\u043a \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b Spring, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u044b Liquibase \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u0442\u0435\u043c \u0438\u043b\u0438 \u0438\u043d\u044b\u043c \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u043e\u043c.<\/p>\n<p><code><strong>application.yml<\/strong><\/code><strong> \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0430\u043c\u0438 Spring<\/strong><\/p>\n<pre><code class=\"yaml\">\/\/ ....  spring:   application:     name: j-sso   liquibase:     enabled: true     change-log: classpath:database\/db.changelog.yaml     contexts: dev, prod    \/\/ ....  --- spring:   config:     activate:       on-profile: production   liquibase:     contexts: prod  --- spring:   config:     activate:       on-profile: development   liquibase:     contexts: prod, dev <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443 \u043d\u0430\u0441 \u043d\u0430\u043a\u0430\u0442\u044f\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0411\u0414 (\u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0430\u043c PostgreSQL).<\/p>\n<h3>\u041d\u0430\u043a\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f maven \u043f\u043b\u0430\u0433\u0438\u043d<\/h3>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u043a\u0430\u043a \u044f \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b, \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 maven: <a href=\"https:\/\/docs.liquibase.com\/tools-integrations\/maven\/getting-started-liquibase-maven.html\" rel=\"noopener noreferrer nofollow\">liquibase-maven-plugin<\/a>. \u0412 \u044d\u0442\u043e\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043d\u0430\u043c \u043d\u0435 \u043d\u0430\u0434\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>database<\/code> \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0441\u0431\u043e\u0440\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u043a\u0446\u0438\u044e <code>&lt;resources>...&lt;\/resounrces><\/code> \u043c\u043e\u0436\u043d\u043e \u0443\u0431\u0440\u0430\u0442\u044c. \u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e <code>pom.xml<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043b\u0430\u0433\u0438\u043d.<\/p>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ .....      &lt;build>         &lt;finalName>${project.artifactId}&lt;\/finalName>         &lt;plugins>             &lt;plugin>                 &lt;groupId>org.springframework.boot&lt;\/groupId>                 &lt;artifactId>spring-boot-maven-plugin&lt;\/artifactId>                 &lt;configuration>                     &lt;finalName>${project.name}&lt;\/finalName>                 &lt;\/configuration>             &lt;\/plugin>             &lt;plugin>                 &lt;groupId>org.liquibase&lt;\/groupId>                 &lt;artifactId>liquibase-maven-plugin&lt;\/artifactId>                 &lt;configuration>                     &lt;propertyFile>${project.basedir}\/database\/liquibase.properties&lt;\/propertyFile>                     &lt;promptOnNonLocalDatabase>false&lt;\/promptOnNonLocalDatabase>                 &lt;\/configuration>             &lt;\/plugin>         &lt;\/plugins>     &lt;\/build> &lt;\/project> <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>database<\/code> \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b &#8212; <code>liquibase.properties<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0411\u0414 \u0438 \u043f\u0443\u0442\u044c \u0434\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e changelog \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p><code><strong>liquibase.properties<\/strong><\/code><\/p>\n<pre><code>changeLogFile=database\/db.changelog.yaml driver=org.postgresql.Driver url=jdbc:postgresql:\/\/localhost:5435\/j-sso username=user password=user contexts=prod, dev <\/code><\/pre>\n<p>\u0414\u043b\u044f \u043d\u0430\u043a\u0430\u0442\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0449\u0438\u0445 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430\u043c, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c maven \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 <code>liquibase.properties<\/code>.<\/p>\n<p>\u0410 \u0441\u0435\u0439\u0447\u0430\u0441, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u043a\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0411\u0414, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 <code>j-sso<\/code>:<\/p>\n<pre><code>mvn liquibase:update -Dliquibase.searchPath=.\/ <\/code><\/pre>\n<p>\u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u043a\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0411\u0414 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0441\u0431\u043e\u0440\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 <code>&lt;executions><\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u0412 \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440\u0435 <code>&lt;phase><\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435.<\/p>\n<p><code><strong>j-sso\/pom.xml \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 liquibase \u043f\u043b\u0430\u0433\u0438\u043d\u0430<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ .....      &lt;build>         &lt;finalName>${project.artifactId}&lt;\/finalName>         &lt;plugins>             &lt;plugin>                 &lt;groupId>org.springframework.boot&lt;\/groupId>                 &lt;artifactId>spring-boot-maven-plugin&lt;\/artifactId>                 &lt;configuration>                     &lt;finalName>${project.name}&lt;\/finalName>                 &lt;\/configuration>             &lt;\/plugin>             &lt;plugin>                 &lt;groupId>org.liquibase&lt;\/groupId>                 &lt;artifactId>liquibase-maven-plugin&lt;\/artifactId>                 &lt;configuration>                     &lt;propertyFile>${project.basedir}\/database\/liquibase.properties&lt;\/propertyFile>                     &lt;promptOnNonLocalDatabase>false&lt;\/promptOnNonLocalDatabase>                 &lt;\/configuration>                 &lt;executions>                     &lt;execution>                         &lt;id>liquibase-update&lt;\/id>                         &lt;phase>process-resources&lt;\/phase>                         &lt;goals>                             &lt;goal>update&lt;\/goal>                         &lt;\/goals>                     &lt;\/execution>                 &lt;\/executions>             &lt;\/plugin>         &lt;\/plugins>     &lt;\/build> &lt;\/project> <\/code><\/pre>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>-Dliquibase.searchPath<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0434\u0432\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430. \u0418\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u0433\u043b\u0430\u0432\u043d\u044b\u0439 changelog \u0444\u0430\u0439\u043b Liquibase \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0434\u0432\u0430\u0436\u0434\u044b. \u0427\u0442\u043e\u0431\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043f\u043e\u0438\u0441\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>liquibase.searchPath<\/code>.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u043a\u0430\u0442\u0430 \u0432\u0441\u0435\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0443 \u043d\u0430\u0441 \u0432 \u0411\u0414 \u0435\u0441\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043d\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<h4>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u0412 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>dao<\/code> \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0443\u0436\u0435 <code>UserEntity<\/code>, \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u0435\u0451 \u043f\u043e\u0434 \u043d\u0430\u0448\u0438 \u043d\u043e\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0438 \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432\u0442\u043e\u0440\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c <code>SystemOauth2Client<\/code>. \u042d\u0442\u0438 \u0434\u0432\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u0431\u0443\u0434\u0443\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446 <code>sso.users<\/code> \u0438 <code>sso.system_oauth2_clients<\/code>. \u0415\u0441\u043b\u0438 <code>SystemOauth2Client<\/code> \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f entity, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-2.2\/j-sso\/src\/main\/java\/ru\/dlabs\/sas\/example\/jsso\/dao\/entity\/SystemOauth2Client.java\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>, \u0442\u043e \u043f\u0440\u043e <code>UserEntity<\/code> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u044f\u0441\u043d\u0438\u0442\u044c.<\/p>\n<p><code><strong>UserEntity.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter @Entity @Table(schema = \"sso\", name = \"users\") public class UserEntity extends VersionedBusinessEntity&lt;UUID> {      @Id     @Column(name = \"user_id\", nullable = false)     @GeneratedValue(strategy = GenerationType.UUID)     private UUID id;     @Column(name = \"email\", nullable = false)     private String email;     @Column(name = \"password_hash\")     private String passwordHash;     @Column(name = \"first_name\", nullable = false)     private String firstName;     @Column(name = \"second_name\", nullable = false)     private String secondName;     @Column(name = \"middle_name\")     private String middleName;     @Column(name = \"birthday\")     private LocalDate birthday;     @Column(name = \"avatar_url\")     private String avatarUrl;     @Column(name = \"active\", nullable = false)     private Boolean active;      @Override     public UUID getId() {         return this.id;     }      @Override     public void setId(UUID id) {         this.id = id;     }  } <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043e\u043d\u0430 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 <code>VersionedBusinessEntity<\/code> \u0438 \u0432 \u043d\u0435\u0439 \u043d\u0435\u0442 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 (<code>created_by<\/code>, <code>created_date<\/code> \u0438 \u0434\u0440.). \u0418 \u0432\u043e\u0442 \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0434\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u0442\u043e, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b.<\/p>\n<p>\u0421\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f &#8212; \u044d\u0442\u043e \u043f\u043e\u043b\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0434\u0430\u0442\u0430\/\u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u043a\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043b \u044d\u0442\u0443 \u0437\u0430\u043f\u0438\u0441\u044c (\u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u043b\u043e\u0433\u0438\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f)<\/p>\n<\/li>\n<li>\n<p>\u0434\u0430\u0442\u0430\/\u0432\u0440\u0435\u043c\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u043a\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u043b \u044d\u0442\u0443 \u0437\u0430\u043f\u0438\u0441\u044c<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u0441\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0443\u043d\u043a\u0442\u044b 1 \u0438 2 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438, \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0435 \u0431\u0430\u0433\u043e\u0432 \u0438\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u044b\u0445 \u043c\u0435\u0441\u0442, \u0434\u043b\u044f \u0431\u0443\u0434\u0443\u0449\u0435\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u0435\u0442 \u0438 \u043d\u0430 \u0437\u0430\u043c\u0435\u043d\u0443 \u0435\u0439 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442) \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u0435\u0439\u0441\u043e\u0432. \u0410 \u0432\u043e\u0442 3-\u0438\u0439 \u043f\u0443\u043d\u043a\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043e\u0434\u043d\u043e\u0439 \u0438 \u0442\u043e \u0436\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u043b\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 &#171;\u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f\u043c\u0438&#187;. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u043f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414 \u0438 \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u0447\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0430\u044f, \u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 <code>OptimisticLockException<\/code> \u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043c\u044b \u0436\u0435 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043b\u043e\u0432\u0438\u0442\u044c \u044d\u0442\u043e\u0442 exception \u0438 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0432\u0441\u0435\u0445 \u0431\u0438\u0437\u043d\u0435\u0441-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u0445, \u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u0445 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0447\u0442\u043e \u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u043e. \u041d\u043e, \u043c\u044b \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f, \u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u043e\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043f\u043e\u043b\u044f: <code>created_by<\/code>, <code>created_date<\/code>, <code>last_updated_by<\/code>, <code>last_updated_date<\/code> &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u043e\u0439. \u0410 \u043f\u043e\u043b\u0435 <code>object_version_number<\/code> \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e, \u043a\u0430\u043a \u0441 \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438, \u0442\u0430\u043a \u0438 \u0431\u0435\u0437. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c, \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>CoreEntity<\/code>, \u0432 \u043d\u0451\u043c \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u0435\u0442\u0442\u0435\u0440 \u0438 \u0441\u0435\u0442\u0442\u0435\u0440 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438. \u0414\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0431\u043e\u0442\u0435, \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0438\u043c \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0430\u0442\u044c.<\/p>\n<p><code><strong>CoreEntity.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">public interface CoreEntity&lt;Id extends Serializable> extends Serializable {      Id getId();      void setId(Id id); } <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>BusinessEntity<\/code>, \u0432 \u043d\u0451\u043c \u0431\u0443\u0434\u0443\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 <code>prePersist()<\/code> \u0438 <code>preUpdate()<\/code>. \u0412 \u044d\u0442\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u0430\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u043f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0438\u043b\u0438 \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438:<\/p>\n<p><code><strong>BusinessEntity.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter @MappedSuperclass public abstract class BusinessEntity&lt;Id extends Serializable> implements CoreEntity&lt;Id> {      public final static String DEFAULT_USER = \"system\";      @Column(name = \"created_by\", nullable = false)     private String createdBy;      @Column(name = \"created_date\", nullable = false)     private LocalDateTime creationDate;      @Column(name = \"last_updated_by\", nullable = false)     private String lastUpdatedBy;      @Column(name = \"last_updated_date\", nullable = false)     private LocalDateTime lastUpdateDate;      @PrePersist     public void prePersist() {         this.creationDate = LocalDateTime.now(TimeZone.getDefault().toZoneId());         this.lastUpdateDate = this.creationDate;          if (StringUtils.isEmpty(this.createdBy)) {             this.createdBy = findCurrentUser();         }         this.lastUpdatedBy = this.createdBy;     }      @PreUpdate     public void preUpdate() {         this.lastUpdateDate = LocalDateTime.now(TimeZone.getDefault().toZoneId());         this.lastUpdatedBy = findCurrentUser();     }      private String findCurrentUser() {         String user = null;         if (SecurityContextHolder.getContext().getAuthentication() != null) {             UserDetails userDetails = null;             if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof UserDetails) {                 userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();             }             user = userDetails != null ? userDetails.getUsername() : null;         }         return user == null ? DEFAULT_USER : user;     } } <\/code><\/pre>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0432\u0430 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430 <code>VersionedBusinessEntity<\/code> \u0438 <code>VersionedEntity<\/code>. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438, \u043f\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@Version<\/code>. \u0422\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 <code>BusinessEntity<\/code>, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>CoreEntity<\/code>. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0440\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0448\u0435\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043e\u0442 <code>VersionedBusinessEntity<\/code> \u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u0435 5 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439. \u041f\u0440\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0442 <code>BusinessEntity<\/code> \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u043a\u0440\u043e\u043c\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0438. \u0410 \u043f\u0440\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0442 <code>VersionedEntity<\/code> \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0440\u0441\u0438\u044e \u0437\u0430\u043f\u0438\u0441\u0438. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043d\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0432 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u0443\u043c\u0430\u0442\u044c \u043e\u0431 \u0438\u0445 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438.<\/p>\n<p><code><strong>VersionedBusinessEntity.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter @MappedSuperclass public abstract class VersionedBusinessEntity&lt;Id extends Serializable> extends BusinessEntity&lt;Id> {      @Version     @Column(name = \"object_version_number\", nullable = false)     private Long version;  } <\/code><\/pre>\n<p><code><strong>VersionedEntity.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter @MappedSuperclass public abstract class VersionedEntity&lt;Id extends Serializable> implements CoreEntity&lt;Id> {      @Version     @Column(name = \"object_version_number\", nullable = false)     private Long version;  } <\/code><\/pre>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u044b\u0442\u043e\u0436\u0438\u043c.<\/p>\n<ol>\n<li>\n<p>\u041c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 Liquibase<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 &#171;\u0440\u0430\u0441\u043a\u0430\u0442\u0430&#187; \u0411\u0414<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f 2-\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 \u043d\u0430\u043a\u0430\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043d\u0438\u0445<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0421\u0423\u0411\u0414 PostgreSQL \u0432 <code>j-sso<\/code><\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0438 \u0434\u043b\u044f \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0449\u0438\u0445<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c:<\/p>\n<ol>\n<li>\n<p>\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c JPA \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f CRUD \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 <code>UserService<\/code><\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0438\u043d <code>RegisteredClientRepository<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0430\u0448\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 \u0432 \u0411\u0414 <code>sso.system_oauth2_clients<\/code><\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c <code>PasswordEncoder<\/code> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c BCrypt \u0445\u0435\u0448-\u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ol>\n<h3>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f JPA \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432, \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>dao\/repository<\/code>. \u0423\u0434\u0430\u043b\u0438\u043c \u0441\u0442\u0430\u0440\u044b\u0439 <code>UserRepository<\/code> \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>SystemOauth2ClientRepository<\/code> \u0438 <code>UserRepository<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u044b \u043e\u0442 <code>JpaRepository<\/code>. \u0414\u0430\u043b\u0435\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>RootAppConfig<\/code>. \u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043e\u0431\u0449\u0438\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 \u043d\u0435 \u043a\u0430\u0441\u0430\u044e\u0449\u0438\u0445\u0441\u044f security. \u0421\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0451\u043c \u0432 \u043d\u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 <code>CORSConfig<\/code>, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043b\u043e\u0434\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b. \u0418 \u0442\u0443\u0442 \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@EnableJpaRepositories<\/code>. \u0414\u0430\u043d\u043d\u0430\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 JPA. \u0423\u043a\u0430\u0436\u0435\u043c \u0432 \u043d\u0435\u0439 \u043f\u0430\u043a\u0435\u0442 \u0441 \u043d\u0430\u0448\u0438\u043c\u0438 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c\u0438 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 <code>basePackages<\/code>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f, \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0412\u0441\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0451\u043c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>config\/security<\/code>. \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043b\u043e \u0440\u0430\u0441\u0442\u0438 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0435\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0442\u043e\u0436\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0443\u0442\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0430\u0445, \u043c\u044b \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0438 security \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c <code>PasswordEncoder<\/code> \u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0431\u0438\u043d\u0430 <code>RegisteredClientRepository<\/code>. \u041f\u0435\u0440\u0432\u043e\u0435 \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 <code>SecurityConfigUtilities<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0431\u0438\u043d:<\/p>\n<p><code><strong>SecurityConfigUtilities.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Configuration(proxyBeanMethods = false) public class SecurityConfigUtilities {      \/\/ ...      @Bean     public PasswordEncoder passwordEncoder() {         return new BCryptPasswordEncoder(10);     }  } <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u0443 <code>AuthenticationManager<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c <code>SecurityConfig<\/code>.<\/p>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @EnableWebSecurity @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {      private final CustomOAuth2UserService customOAuth2UserService;     private final CustomUserDetailsService userDetailService;      \/\/ inject-\u0438\u043c \u043d\u0430\u0448 password encoder \u0431\u0438\u043d     private final PasswordEncoder passwordEncoder;      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         SocialConfigurer socialConfigurer = new SocialConfigurer()                 .oAuth2UserService(customOAuth2UserService);         http.apply(socialConfigurer);          http.getSharedObject(AuthenticationManagerBuilder.class)                 .userDetailsService(userDetailService)                 \/\/ \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c                 .passwordEncoder(passwordEncoder);          http.authorizeHttpRequests(authorize ->                 authorize.anyRequest().authenticated()         );         return http.formLogin(withhttps:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.2Defaults()).build();     } } <\/code><\/pre>\n<p>\u0410 \u043a\u0430\u043a \u0436\u0435 \u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 <code>AuthenticationProvider<\/code> \u0434\u043b\u044f client authentication? \u0412\u043e\u0442 \u0442\u0443\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u0432\u0441\u0451 \u0441\u043b\u043e\u0436\u043d\u043e. \u0427\u0442\u043e\u0431\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u044f\u0432\u043d\u0443\u044e, \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u0440\u043e\u0439\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 &#171;\u0441\u0435\u043c\u044c \u043a\u0440\u0443\u0433\u043e\u0432 \u0430\u0434\u0430 spring&#187; \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0443\u0447\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438 \u0442\u0430\u043a \u0435\u0441\u0442\u044c \u043f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443 \u0438 \u043e\u043d\u0438 \u043d\u0430\u0441 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 <code>OAuth2AuthorizationServerConfigurer<\/code>.<\/p>\n<p>\u041d\u0430\u0439\u0434\u0451\u043c \u0442\u0430\u043c DSL <code>clientAuthentication()<\/code>. \u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u0432 <code>OAuth2ClientAuthenticationConfigurer<\/code> \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f <code>AuthenticationProvider<\/code> \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/6ff\/60e\/df4\/6ff60edf4320df6e32b6ac858077f86c.png\" alt=\"OAuth2ClientAuthenticationConfigurer, \u043c\u0435\u0442\u043e\u0434 createDefaultAuthenticationProviders\" title=\"OAuth2ClientAuthenticationConfigurer, \u043c\u0435\u0442\u043e\u0434 createDefaultAuthenticationProviders\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/6ff\/60e\/df4\/6ff60edf4320df6e32b6ac858077f86c.png\"\/><\/p>\n<div><figcaption>OAuth2ClientAuthenticationConfigurer, \u043c\u0435\u0442\u043e\u0434 createDefaultAuthenticationProviders<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <code>createDefaultAuthenticationProviders<\/code> \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 143 \u0441\u0442\u0440\u043e\u043a\u0435 \u043e\u043d \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0431\u0438\u043d <code>PasswordEncoder<\/code> \u0438\u0437 <code>HttpSecurity<\/code>. \u0410 \u0435\u0441\u043b\u0438 \u043c\u044b \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u0435\u0449\u0451 \u0447\u0443\u0442\u044c \u0433\u043b\u0443\u0431\u0436\u0435, \u0432 \u043c\u0435\u0442\u043e\u0434 <code>getOptionalBean<\/code>, \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c \u043e\u043d \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0431\u0438\u043d \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0438\u0437 <code>ApplicationContext<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/471\/47b\/84b\/47147b84b61baa086bd724ca877b1dd5.png\" alt=\"OAuth2ConfigurerUtils, \u043c\u0435\u0442\u043e\u0434 getOptionalBean\" title=\"OAuth2ConfigurerUtils, \u043c\u0435\u0442\u043e\u0434 getOptionalBean\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/471\/47b\/84b\/47147b84b61baa086bd724ca877b1dd5.png\"\/><\/p>\n<div><figcaption>OAuth2ConfigurerUtils, \u043c\u0435\u0442\u043e\u0434 getOptionalBean<\/figcaption><\/div>\n<\/figure>\n<p>\u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0431\u0438\u043d <code>PasswordEncoder<\/code> \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>passwordEncoder<\/code> \u0438 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430\u0445 client authentication. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0432 \u0431\u0438\u043d <code>passwordEncoder<\/code> \u0432\u0435\u0437\u0434\u0435 \u0435\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>RegisteredClientRepository<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>SystemOauth2ClientRepository<\/code> \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0432 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <code>DaoRegisteredClientRepository<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>RegisteredClientRepository<\/code>. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0435\u0451 \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-2.2\/j-sso\/src\/main\/java\/ru\/dlabs\/sas\/example\/jsso\/dao\/repository\/DaoRegisteredClientRepository.java\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>. \u0421\u0442\u0430\u0440\u044b\u0439 \u0431\u0438\u043d <code>registeredClientRepository<\/code> \u0432 <code>AuthorizationServerConfig<\/code> \u043c\u043e\u0436\u043d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0443\u0434\u0430\u043b\u0438\u0442\u044c.<\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 <code>UserRepository<\/code> \u0441 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\u043c JPA, \u0442\u043e \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445 \u043d\u0430\u043c \u0443\u0436\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0435 \u043d\u0430\u0434\u043e. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>findByEmail<\/code>. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u043d\u0430\u0434\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@Transactional<\/code> \u043d\u0430\u0434 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<p><code><strong>UserRepository.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Repository public interface UserRepository extends JpaRepository&lt;UserEntity, Long> {      UserEntity findByEmail(String email); } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c. \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0421\u0423\u0411\u0414 \u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Liquibase \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u0411\u0414. \u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0441\u0451 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u0438, \u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0431\u0435\u0440\u0451\u0442\u0441\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f. \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0432\u044b \u043f\u0440\u043e\u0439\u0434\u0451\u0442\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Yandex, \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 <code>sso.users<\/code> \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u0442 Yandex.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/8c8\/470\/3c6\/8c84703c634cf77eec23937cef6baf3b.png\" alt=\"\u0422\u0430\u0431\u043b\u0438\u0446\u0430 `sso.users` \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Yandex\" title=\"\u0422\u0430\u0431\u043b\u0438\u0446\u0430 `sso.users` \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Yandex\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/8c8\/470\/3c6\/8c84703c634cf77eec23937cef6baf3b.png\"\/><\/p>\n<div><figcaption>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 `sso.users` \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Yandex<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0430\u043a\u0436\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c, \u0434\u0430\u043d\u043d\u043e\u0439 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 (\u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0430\u0440\u043e\u043b\u044c, \u0430 \u0445\u0435\u0448 \u043f\u0430\u0440\u043e\u043b\u044f), \u0442\u043e \u043c\u043e\u0436\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0434\u0430\u043d\u043d\u044b\u0439 email, \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0438 \u043f\u0430\u0440\u043e\u043b\u044e. \u0417\u0434\u043e\u0440\u043e\u0432\u043e, \u043d\u0435 \u043f\u0440\u0430\u0432\u0434\u0430 \u043b\u0438? ?<\/p>\n<blockquote>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.2\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 2.3: \u041f\u0440\u043e\u0441\u0442\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u043e \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438<\/h3>\n<p>\u0412\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u043e\u0431\u0445\u043e\u0434\u0438\u043b\u0438 \u0441\u0442\u043e\u0440\u043e\u043d\u043e\u0439 \u0440\u043e\u043b\u0438 \u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0438\u043c SSO. \u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e \u043d\u0438\u0445 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u043e\u043b\u0435\u0432\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u043c\u043d\u0435 \u0434\u043e\u0432\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u043e\u043b\u0435\u0432\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u043d\u043e \u0435\u0441\u0442\u044c 3 \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f. \u0418\u0445 \u043c\u044b \u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c.<\/p>\n<h4>\u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442<\/h4>\n<p>\u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439, \u043e\u0431\u044b\u0447\u043d\u043e \u043e\u0431\u0438\u0442\u0430\u044e\u0449\u0438\u0439 \u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0438\u043b\u0438 \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u0423 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u043e\u043b\u044c, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0442\u043e\u0442 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0420\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0435\u0433\u043e endpoint-\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0430. \u0425\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u043d\u0435\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u043a\u043d\u0438\u0433\u0438 \u0438 \u0435\u0441\u0442\u044c 3 \u0442\u0438\u043f\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439:<\/p>\n<ol>\n<li>\n<p><strong>\u0421\u0442\u0443\u0434\u0435\u043d\u0442<\/strong> &#8212; \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043f\u043e\u0438\u0441\u043a\u0443 \u043a\u043d\u0438\u0433\u0438, \u0447\u0442\u0435\u043d\u0438\u044e \u043a\u043d\u0438\u0433\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438<\/strong> &#8212; \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f, \u0447\u0442\u043e \u0438 \u0441\u0442\u0443\u0434\u0435\u043d\u0442. \u041d\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044e\/\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044e \u043a\u043d\u0438\u0433\u0438, \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u044f \u043a\u043d\u0438\u0433\u0438, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043d\u043e\u0432\u043e\u0441\u0442\u044f\u043c\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u0435\u043f\u043e\u0434\u0430\u0432\u0430\u0442\u0435\u043b\u044c<\/strong> &#8212; \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f, \u0447\u0442\u043e \u0438 \u0441\u0442\u0443\u0434\u0435\u043d\u0442. \u041d\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043a\u043d\u0438\u0433.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c 3 \u0440\u043e\u043b\u0438: STUDENT, ADMIN, TEACHER. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0437\u0430\u043f\u0440\u0435\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0442\u0435\u043c \u0438\u043b\u0438 \u0438\u043d\u044b\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<ol>\n<li>\n<p>\u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043b\u043e\u043d\u043a\u0443 <code>role<\/code> \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 <code>users<\/code><\/p>\n<\/li>\n<li>\n<p>\u0438\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 <code>roles<\/code> \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u044f\u0437\u044c \u043e\u0434\u0438\u043d \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u043c\u0435\u0436\u0434\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438 <code>roles<\/code> \u0438 <code>users<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0440\u043e\u043b\u0435\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u043e \u043f\u043e\u0434\u0432\u0435\u0440\u0436\u0435\u043d\u0430 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0438 \u0435\u0441\u043b\u0438 \u0432\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f, \u0442\u043e \u0435\u0451 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043d\u0435 \u0441\u0442\u043e\u0438\u0442. \u041d\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0435\u043c\u043e \u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u0440\u043e\u043b\u0435\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442. \u041e\u043d\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430 \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u0442 \u043b\u0438\u0448\u043d\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0432 \u043a\u043e\u0434.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0434\u0432\u0435 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0411\u0414 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c03\/9c5\/b1a\/c039c5b1a7bd55caab693e93c15cb977.png\" alt=\"\u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043b\u043e\u043d\u043a\u0443 role \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 users\" title=\"\u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043b\u043e\u043d\u043a\u0443 role \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 users\" width=\"425\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c03\/9c5\/b1a\/c039c5b1a7bd55caab693e93c15cb977.png\"\/><\/p>\n<div><figcaption>\u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043b\u043e\u043d\u043a\u0443 role \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 users<\/figcaption><\/div>\n<\/figure>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/110\/bfe\/25d\/110bfe25d99e40000d21c0988b978373.png\" alt=\"\u0420\u043e\u043b\u0438 \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443\" title=\"\u0420\u043e\u043b\u0438 \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443\" width=\"775\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/110\/bfe\/25d\/110bfe25d99e40000d21c0988b978373.png\"\/><\/p>\n<div><figcaption>\u0420\u043e\u043b\u0438 \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443<\/figcaption><\/div>\n<\/figure>\n<h4>\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442<\/h4>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0447\u0443\u0442\u044c \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0431\u0430\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0440\u044f\u0434 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043d\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u0418 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a \u0437\u0430\u0445\u043e\u0442\u0435\u043b \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u043e\u043b\u0438, \u0434\u0430\u0432\u0430\u044f \u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0440\u043e\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 (\u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u044d\u0442\u043e endpoint-\u044b). \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0440\u043e\u043b\u0435\u0439, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0440\u044f\u0434\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u043c\u044b \u043d\u0435 \u043e\u0431\u043e\u0439\u0434\u0451\u043c\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u0432\u0441\u0435\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 &#8212; \u043d\u0435\u043a\u0430\u044f &#171;\u043c\u0438\u043d\u0438 \u0440\u043e\u043b\u044c&#187; \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 endpoint \u0441\u0432\u043e\u044f \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f. \u0410 \u0434\u0430\u043b\u0435\u0435, \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 &#8212; \u044d\u0442\u043e \u0438 \u0431\u0443\u0434\u0443\u0442 \u0440\u043e\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p>\u041f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 <code>authorities<\/code> (\u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438), \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 <code>roles<\/code> (\u0440\u043e\u043b\u0438) \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0441\u0432\u044f\u0437\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c. \u0421\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0438 \u0440\u043e\u043b\u044f\u043c\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c, \u0442\u0430\u043a \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043a \u043e\u0434\u043d\u043e\u043c\u0443. \u0427\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441\u043e \u0441\u0432\u044f\u0437\u044c\u044e \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0434\u0432\u0435 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0411\u0414 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/f7e\/3b1\/675\/f7e3b16755c0c6ef3174cc02baca9532.png\" alt=\"\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0441\u0432\u044f\u0437\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a \u043e\u0434\u043d\u043e\u043c\u0443\" title=\"\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0441\u0432\u044f\u0437\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a \u043e\u0434\u043d\u043e\u043c\u0443\" width=\"585\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/f7e\/3b1\/675\/f7e3b16755c0c6ef3174cc02baca9532.png\"\/><\/p>\n<div><figcaption>\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0441\u0432\u044f\u0437\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a \u043e\u0434\u043d\u043e\u043c\u0443<\/figcaption><\/div>\n<\/figure>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/62b\/ad8\/6f1\/62bad86f11fbb31735b37d323f19c883.png\" alt=\"\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0441\u0432\u044f\u0437\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c\" title=\"\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0441\u0432\u044f\u0437\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c\" width=\"615\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/62b\/ad8\/6f1\/62bad86f11fbb31735b37d323f19c883.png\"\/><\/p>\n<div><figcaption>\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0441\u0432\u044f\u0437\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c<\/figcaption><\/div>\n<\/figure>\n<h4>\u0422\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442<\/h4>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u044d\u0442\u043e \u0432\u0435\u0442\u0432\u044c \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438. \u041e\u0431\u044b\u0447\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u043d\u044c \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445. \u042d\u0442\u0430 \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0442\u0430\u043a\u0436\u0435 \u0438\u0437 \u0440\u043e\u043b\u0435\u0439 \u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439, \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043f\u0435\u0440\u044c, \u043f\u043e\u043c\u0438\u043c\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044e \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043e\u0447\u0435\u043d\u044c \u0433\u0438\u0431\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0434\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/afc\/741\/174\/afc74117411d02c5ecc4b5fd94dccc95.png\" alt=\"\u0422\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438\" title=\"\u0422\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/afc\/741\/174\/afc74117411d02c5ecc4b5fd94dccc95.png\"\/><\/p>\n<div><figcaption>\u0422\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438<\/figcaption><\/div>\n<\/figure>\n<h4>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0433\u043e<\/h4>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0432 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u0438 \u0440\u043e\u043b\u0438 \u043d\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u043d\u0443\u0436\u043d\u044b. \u041d\u043e \u043c\u044b \u0437\u043d\u0430\u0435\u043c \u0447\u0442\u043e:<\/p>\n<ol>\n<li>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Spring Security<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 endpoint-\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0423 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (pet-\u043f\u0440\u043e\u0435\u043a\u0442\u044b, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u0441\u0442\u043e\u0438\u043c \u043d\u0430\u0448 SSO), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0438 \u0440\u043e\u043b\u044f\u043c\u0438 \u043d\u0430\u0448\u0435\u043c\u0443 SSO<\/p>\n<\/li>\n<\/ol>\n<p>\u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0442\u043e\u0447\u043d\u043e \u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442. \u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u043c \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f\u043c\u0438, \u0430 \u043f\u043e\u0442\u043e\u043c \u0438\u0445 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0440\u043e\u043b\u0438. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0447\u0442\u043e Spring Security \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u0415\u0441\u0442\u044c \u043b\u0438 \u0441\u043c\u044b\u0441\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442? \u0414\u0443\u043c\u0430\u044e \u0447\u0442\u043e \u043d\u0435\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0431\u044b\u043b\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043a \u044d\u0442\u043e\u043c\u0443. \u0410 \u043d\u0430\u0448\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0435 \u0442\u0430\u043a\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0438 \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043c\u044b \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435, \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u043e, \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u0442\u0430\u043d\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0439. \u0412\u0441\u0451 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f\u043c\u0438, \u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f, \u043a\u0430\u043a \u0438 \u0431\u044b\u043b\u043e.<\/p>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0411\u0414 \u043d\u0430\u0448\u0435\u0439 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/e2a\/d4b\/f48\/e2ad4bf48ec0b4cef61726cad232c798.png\" alt=\"\u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438\" title=\"\u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e2a\/d4b\/f48\/e2ad4bf48ec0b4cef61726cad232c798.png\"\/><\/p>\n<div><figcaption>\u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u0445 \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.3\/j-sso\/database\/release-1.0.0\/object\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0438 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.3\/j-sso\/src\/main\/java\/ru\/dlabs\/sas\/example\/jsso\/dao\/entity\" rel=\"noopener noreferrer nofollow\">\u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446<\/a> \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0445\u043e\u0447\u0443 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u0443 \u0441\u043b\u043e\u0432 \u043e \u043f\u043e\u043b\u044f\u0445 <code>role_code<\/code>, <code>authority_code<\/code> \u0438 <code>system_code<\/code>.<\/p>\n<p>\u0423 \u0432\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441, \u0430 \u0437\u0430\u0447\u0435\u043c \u043d\u0430\u043c \u044d\u0442\u0438 \u043f\u043e\u043b\u044f \u043a\u043e\u0433\u0434\u0430 \u0438 \u0442\u0430\u043a \u0435\u0441\u0442\u044c <code>role_id<\/code> \u0438 <code>authority_id<\/code>? \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0441 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f\u043c\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u043a\u043e\u0434\u0435, \u0438 \u0442\u0430\u043c \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u043a\u0438\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u043e\u0438\u043c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0442\u043e \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u043d. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430, \u0442\u043e \u0435\u0451 \u043a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c <code>ACCESS_CREATE_ACCOUNT<\/code>. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0438 \u0441 \u0440\u043e\u043b\u044f\u043c\u0438.<\/p>\n<p><code>system_code<\/code> &#8212; \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043a\u043e\u0434 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (\u043f\u0440\u043e\u0435\u043a\u0442\u0430), \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u043e\u043b\u044c \u0438\u043b\u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430. \u042f \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u044e, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u0434\u043b\u044f \u043c\u043e\u0438\u0445 pet-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f <code>j-sso<\/code>. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u043e\u0433\u0434\u0430 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u0430\u043a\u0430\u044f \u0440\u043e\u043b\u044c \u0438\u043b\u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u0435\u043b\u0430\u044e\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043b\u043e\u0436\u0438\u043b\u0438 \u043e\u0441\u043d\u043e\u0432\u0443 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u043c \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u043e\u043b\u044c \u0441 \u043a\u043e\u0434\u043e\u043c <code>USER_SSO<\/code> &#8212; \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e <code>j-sso<\/code>. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u043e\u0433\u0434\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439:<\/p>\n<ol>\n<li>\n<p><code>GET_OWN_DATA<\/code> &#8212; \u041f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p><code>CHANGE_OWN_DATA<\/code> &#8212; \u041f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p><code>CHANGE_OWN_PASSWORD<\/code> &#8212; \u041f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p><code>DELETE_OWN_ACCOUNT<\/code> &#8212; \u041f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043b\u044e\u0431\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u0441\u0440\u0430\u0437\u0443 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c SSO \u0438 \u0431\u0435\u0437 \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 SSO, \u0442\u043e \u043f\u0443\u0441\u0442\u044c \u044d\u0442\u0430 \u0440\u043e\u043b\u044c \u0441\u0440\u0430\u0437\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c <code>DefaultUserService<\/code>. \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0442\u0430\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex.<\/p>\n<p><code><strong>DefaultUserService.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Service @RequiredArgsConstructor public class DefaultUserService implements UserService {      \/\/ ......      \/**      * \u041c\u0435\u0442\u043e\u0434 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\/\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 UserEntity \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 OAuth2User \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u0437 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 Github      *\/     private UserEntity saveUserFromGithab(OAuth2User userDto) {         String email = userDto.getAttribute(\"email\");         UserEntity user = this.getEntityByEmail(email); \/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 UserEntity \u043f\u043e email         \/\/ ........     }      \/\/ ......      \/**      * \u041c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 UserEntity \u043f\u043e email      * \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c email \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0432 \u0411\u0414, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c      *\/     private UserEntity getEntityByEmail(String email) {         if (email == null) {             throw new AuthException(AuthErrorCode.EMAIL_IS_EMPTY);         }         UserEntity user = this.userRepository.findByEmail(email);         if (user == null) {             user = new UserEntity();             user.setEmail(email);             user.setActive(true);             \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u043e\u043b\u044c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e             user.setRoles(List.of(roleRepository.getDefaultRole()));         }         return user;     } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0448 <code>AuthorizedUserMapper<\/code> \u0438 \u0434\u0430\u043b\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<p><code><strong>AuthorizedUserMapper.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @UtilityClass public class AuthorizedUserMapper {      public AuthorizedUser map(UserEntity entity, AuthProvider provider) {         \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 \u0438\u0437 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 builder         List&lt;GrantedAuthority> authorities = getUserAuthorities(entity);         return AuthorizedUser.builder(entity.getEmail(), entity.getPasswordHash(), authorities)                 .id(entity.getId())                 .firstName(entity.getFirstName())                 .secondName(entity.getSecondName())                 .middleName(entity.getMiddleName())                 .birthday(entity.getBirthday())                 .avatarUrl(entity.getAvatarUrl())                 .build();     }      \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 \u0438\u0437 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 SimpleGrantedAuthority     public List&lt;GrantedAuthority> getUserAuthorities(UserEntity entity) {         return entity.getRoles().stream()                 .filter(RoleEntity::getActive)                 .flatMap(role -> role.getAuthorities().stream())                 .filter(AuthorityEntity::getActive)                 .map(authority -> new SimpleGrantedAuthority(authority.getCode()))                 .collect(Collectors.toList());     } } <\/code><\/pre>\n<p>\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0411\u0414 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Liquibase, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 <code>j-sso<\/code> \u0438 <code>test-client<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 GitHub \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/aee\/e35\/424\/aeee354243d9f4caeab7f78776d5704c.png\" alt=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f authorities\" title=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f authorities\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/aee\/e35\/424\/aeee354243d9f4caeab7f78776d5704c.png\"\/><\/p>\n<div><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f authorities<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u0432\u0441\u0451 \u0447\u0442\u043e \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0438 \u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438. \u042d\u0442\u043e \u0441 \u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c endpoint-\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f\u043c\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@PreAuthorize<\/code>. \u0412 \u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u044d\u0442\u043e\u043c\u0443, \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u0432 <code>j-service<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0431\u043b\u044e\u043b\u0438 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f Spring Security \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 introspection endpoint.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0435\u0433\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@PreAuthorize<\/code>. \u041d\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u0430\u043d\u043d\u0430\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c Spring Security \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u044d\u0442\u0438\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 <code>SecurityConfig<\/code> \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@EnableMethodSecurity<\/code>.<\/p>\n<p><code><strong>TestController.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @RestController public class TestController {      @GetMapping(\"\/test\")     @PreAuthorize(\"hasAnyAuthority('GET_OWN_DATA')\")     public String test() {         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();         return authentication.getName();     } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438 \u043f\u0440\u043e\u0439\u0434\u0451\u0442\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e, \u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 endpoint \u0432\u0435\u0440\u043d\u0451\u0442 \u0432\u0430\u043c email \u0430\u0434\u0440\u0435\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0415\u0441\u043b\u0438 \u0436\u0435 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0435\u0442 \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>@PreAuthorize(\"hasAnyAuthority('NOT_EXISTING_AUTHORITY')\")<\/code>, \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0442\u0430\u043a\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 endpoint, \u0442\u043e \u0432 \u043e\u0442\u0432\u0435\u0442 \u0443\u0436\u0435 \u043f\u0440\u0438\u0434\u0451\u0442 403 \u043e\u0448\u0438\u0431\u043a\u0430 &#8212; \u0434\u043e\u0441\u0442\u0443\u043f \u0437\u0430\u043f\u0440\u0435\u0449\u0451\u043d.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <code>j-service<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@PreAuthorize(\"hasAnyAuthority('GET_OWN_DATA')\")<\/code> \u043d\u0430\u0434 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c endpoint. \u0418 \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u0432 <code>ResourceServerConfig<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@EnableMethodSecurity<\/code>. \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>test-client<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u043c access \u0442\u043e\u043a\u0435\u043d \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 endpoint \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <code>j-service<\/code>. \u0418 \u0442\u0443\u0442 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c&#8230; \u041e\u0448\u0438\u0431\u043a\u0443 ?<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/245\/15a\/91a\/24515a91a62e22595ffab2c356876a1f.png\" alt=\"Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438\" title=\"Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/245\/15a\/91a\/24515a91a62e22595ffab2c356876a1f.png\"\/><\/p>\n<div><figcaption>Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u043d\u0430 \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u043c\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u043a\u043e\u0433\u0434\u0430 jackson \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430, \u0438\u0437-\u0437\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u0414\u0430 \u0438 \u0432\u043e\u043e\u0431\u0449\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 DTO \u043a\u043e\u0442\u043e\u0440\u0443\u044e jackson \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c:<\/p>\n<p><code><strong>IntrospectionPrincipal.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class IntrospectionPrincipal {      private UUID id;     private String firstName;     private String secondName;     private String middleName;     private LocalDate birthday;     private String avatarUrl;     private String username;     private String email;     private Collection&lt;? extends GrantedAuthority> authorities; } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 <code>authorities<\/code>, \u0443\u043a\u0430\u0437\u0430\u043d \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u044b\u0439 \u0442\u0438\u043f. \u0421\u0442\u043e\u0438\u0442 \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 jackson &#171;\u043d\u0435 \u043f\u0440\u043e\u0449\u0430\u0435\u0442&#187; \u0438 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u043a\u0430\u043a \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0440\u043e\u043a. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445. \u0410 \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441 <code>IntrospectionPrincipal<\/code> \u0432 <code>j-sso<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p><code><strong>j-sso\/IntrospectionPrincipal.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Builder @AllArgsConstructor public class IntrospectionPrincipal {      private UUID id;     private String firstName;     private String secondName;     private String middleName;     private LocalDate birthday;     private String avatarUrl;     private String username;     private String email;     private List&lt;String> authorities;      public static IntrospectionPrincipal build(AuthorizedUser authorizedUser) {         if (authorizedUser == null) {             return null;         }          \/\/ \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0440\u043e\u043a \u0438\u0437 authorities \u0432 AuthorizedUser         List&lt;String> authorities = Collections.emptyList();         if (authorizedUser.getAuthorities() != null) {             authorities = authorizedUser.getAuthorities()                     .stream()                     .map(GrantedAuthority::getAuthority)                     .collect(Collectors.toList());         }          return IntrospectionPrincipal.builder()                 .id(authorizedUser.getId())                 .firstName(authorizedUser.getFirstName())                 .secondName(authorizedUser.getSecondName())                 .middleName(authorizedUser.getMiddleName())                 .birthday(authorizedUser.getBirthday())                 .avatarUrl(authorizedUser.getAvatarUrl())                 .username(authorizedUser.getUsername())                 .email(authorizedUser.getEmail())                 \/\/ \u0441\u0435\u0442\u0438\u043c \u0432\u044b\u0448\u0435-\u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439                 .authorities(authorities)                 .build();     } } <\/code><\/pre>\n<p>\u0412 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 <code>j-service<\/code> \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u0438\u043f \u0443 \u043f\u043e\u043b\u044f <code>authorities<\/code>. \u0410 \u043c\u0435\u0442\u043e\u0434\u0435 <code>build<\/code> \u043a\u043b\u0430\u0441\u0441\u0430 <code>AuthorizedUser<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 <code>SimpleGrantedAuthority<\/code> \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0441\u0442\u0440\u043e\u043a (<a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-2.3\/j-service\/src\/main\/java\/ru\/dlabs\/sas\/example\/jservice\/dto\/AuthorizedUser.java\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430<\/a>).<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e. \u041f\u0440\u043e\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430, \u0438 \u0432\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c \u0447\u0442\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <code>@PreAuthorize<\/code> \u0432 <code>j-service<\/code> \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u0438 \u0432 <code>j-sso<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/daa\/052\/59e\/daa05259e1adbddde81bdbdc80623d6f.png\" alt=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043a j-service \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c GET_OWN_DATA\" title=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043a j-service \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c GET_OWN_DATA\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/daa\/052\/59e\/daa05259e1adbddde81bdbdc80623d6f.png\"\/><\/p>\n<div><figcaption>\u0417\u0430\u043f\u0440\u043e\u0441 \u043a j-service \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c GET_OWN_DATA<\/figcaption><\/div>\n<\/figure>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/8e8\/7a7\/b08\/8e87a7b08cd6b4c40172365fdd7bbc1c.png\" alt=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043a j-service \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c NOT_EXISTING_AUTHORITY\" title=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043a j-service \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c NOT_EXISTING_AUTHORITY\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/8e8\/7a7\/b08\/8e87a7b08cd6b4c40172365fdd7bbc1c.png\"\/><\/p>\n<div><figcaption>\u0417\u0430\u043f\u0440\u043e\u0441 \u043a j-service \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c NOT_EXISTING_AUTHORITY<\/figcaption><\/div>\n<\/figure>\n<h4>\u041f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u0438 Spring<\/h4>\n<p>\u0421 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e\u0448\u043b\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <code>Spring Boot<\/code> \u0438 <code>Spring Authorization Server<\/code> \u0443\u0441\u043f\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435. \u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 Spring Boot <code>3.1.1<\/code>, Spring Authorization Server <code>1.1.1<\/code>. \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u043d\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u0432\u0441\u0451.<\/p>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0438 DSL \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e \u0442\u0438\u043f\u0443 builder. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c DSL \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c. \u042d\u0442\u043e \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0437\u0430\u0442\u0440\u043e\u043d\u0443\u043b\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043a\u043b\u0430\u0441\u0441 &#8212; \u044d\u0442\u043e <code>SocialConfigurer<\/code>. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 User Service \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u0447\u0443\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0435\u0433\u043e.<\/p>\n<p><code><strong>SocialConfigurer.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Setter @Accessors(chain = true, fluent = true) public class SocialConfigurer extends AbstractHttpConfigurer&lt;SocialConfigurer, HttpSecurity> {      private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User> oAuth2UserService;     private AuthenticationFailureHandler failureHandler;     private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();      @Override     public void init(HttpSecurity http) throws Exception {         http.oauth2Login(oauth2Login -> {             if (this.oAuth2UserService != null) {                 \/\/ \u0431\u044b\u043b\u043e                 \/\/ oauth2Login.userInfoEndpoint().userService(this.oAuth2UserService);                  \/\/ \u0441\u0442\u0430\u043b\u043e                 oauth2Login.userInfoEndpoint(customizer -> {                     customizer.userService(this.oAuth2UserService);                 });             }             if (this.successHandler != null) {                 oauth2Login.successHandler(this.successHandler);             }             if (this.failureHandler != null) {                 oauth2Login.failureHandler(this.failureHandler);             }         });     } } <\/code><\/pre>\n<h3>\u0420\u0435\u0437\u044e\u043c\u0435<\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 Resource Server \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e SSO. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0421\u0423\u0411\u0414 PostgreSQL \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0440\u0430\u0441\u043a\u0430\u0442\u0430 \u0441\u0445\u0435\u043c\u044b \u0411\u0414. \u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446 \u0411\u0414 \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e \u043a\u043e\u0434\u0443, \u0447\u0442\u043e\u0431\u044b <code>j-sso<\/code> \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0442\u0440\u0438 \u0442\u0438\u043f\u0430 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0435\u0451 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442. \u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u0440\u043e\u043b\u0438 \u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438, \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 Spring Security.<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u0438 \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h3>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h3>\n<ol>\n<li>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f <a href=\"https:\/\/habr.com\/ru\/articles\/737548\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/servlet\/oauth2\/resource-server\" rel=\"noopener noreferrer nofollow\">Spring OAuth 2.0 Resource Server<\/a><\/p>\n<\/li>\n<li>\n<p>Github <a href=\"https:\/\/github.com\/spring-projects\/spring-security\/tree\/main\/oauth2\/oauth2-resource-server\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Spring OAuth2 Resource Server<\/a><\/p>\n<\/li>\n<li>\n<p>PostgreSQL image. <a href=\"https:\/\/hub.docker.com\/_\/postgres\" rel=\"noopener noreferrer nofollow\">Docker Hub<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/spring.io\/projects\/spring-data\" rel=\"noopener noreferrer nofollow\">Spring Data<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/spring.io\/projects\/spring-data-jpa\" rel=\"noopener noreferrer nofollow\">Spring Data JPA<\/a><\/p>\n<\/li>\n<li>\n<p>\u0413\u0430\u0439\u0434 \u043f\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e Spring Data JPA <a href=\"https:\/\/spring.io\/guides\/gs\/accessing-data-jpa\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/github.com\/brettwooldridge\/HikariCP#gear-configuration-knobs-baby\" rel=\"noopener noreferrer nofollow\">HikariCP<\/a><\/p>\n<\/li>\n<li>\n<p>HikariCP <a href=\"https:\/\/github.com\/brettwooldridge\/HikariCP\/wiki\/MBean-(JMX)-Monitoring-and-Management\" rel=\"noopener noreferrer nofollow\">MBean (JMX) Monitoring and Management<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/docs.liquibase.com\/tools-integrations\/maven\/getting-started-liquibase-maven.html\" rel=\"noopener noreferrer nofollow\">liquibase-maven-plugin<\/a><\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/746698\/\"> https:\/\/habr.com\/ru\/articles\/746698\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u0438 \u043c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u043d\u0430\u0448\u0443 \u0441\u0435\u0440\u0438\u044e \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e SSO. \u0412 <a href=\"https:\/\/habr.com\/ru\/articles\/737548\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043e\u0441\u043d\u043e\u0432\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043d\u044e\u0430\u043d\u0441\u043e\u0432 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u043a \u0441 <code>Spring Authorization Server<\/code>, \u0442\u0430\u043a \u0438 \u0441 <code>Spring Security<\/code>, <code>Spring OAuth2 Client<\/code>. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 &#171;Social login&#187; \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e SSO \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>\u041d\u043e, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043e\u043a\u0443\u043d\u0451\u043c\u0441\u044f \u0432 \u043c\u0438\u0440 Spring, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u0438 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u0442\u0430\u0442\u0443\u0441<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 Spring Boot \u0438 Spring Authorization Server<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u043d\u0438 \u0441\u043b\u0435\u0433\u043a\u0430 \u043f\u043e\u0434\u043d\u044f\u043b\u0438\u0441\u044c: Spring Boot <code>3.1.1<\/code> \u0438 Spring Authorization Server <code>1.1.1<\/code>. \u041c\u044b \u0438\u0445 \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Java 17<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 SPA Vue.JS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0444\u0440\u043e\u043d\u0442\u0430 SSO<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Redis \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u044d\u0448 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 (\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u0442.\u0434.)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 PostgreSQL \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c Swagger \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0442\u0430\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u0442\u0430\u0442\u0443\u0441<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 SSO \u0447\u0435\u0440\u0435\u0437 \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430\/\u043f\u0430\u0440\u043e\u043b\u044f<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 SSO \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 OAuth2.1 \u0434\u043b\u044f \u043c\u043e\u0438\u0445 pet-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0430\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u043d\u0430 SSO. \u041c\u044b \u0435\u0433\u043e \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 vuejs \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (test-client). \u041d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c OAuth2 Resource Server<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u043f\u043e \u0442\u043e\u043a\u0435\u043d\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 SSO<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u043e\u0440\u043c\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 SSO<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438 (\u043e\u0442\u0437\u044b\u0432 \u0442\u043e\u043a\u0435\u043d\u0430, \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0435\u0441\u0441\u0438\u0439 \u0438 \u0442.\u0434.)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0430\u0448\u0435 \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435, \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u0432 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435.<\/p>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 2.1: \u0421\u043a\u0440\u0435\u0441\u0442\u0438\u043c \u043d\u0430\u0448 SSO \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 OAuth2 Resource Server<\/h3>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 SSO \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <code>Spring Authorization Server<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c introspection endpoint \u043f\u043e\u043c\u0438\u043c\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u0412 Spring Security \u0435\u0441\u0442\u044c <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/servlet\/oauth2\/resource-server\/index.html\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0434\u043f\u0440\u043e\u0435\u043a\u0442<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0435\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0438\u043c\u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f\u043c\u0438 (authorities) \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0439, \u0442\u0430\u043a\u043e\u043c\u0443 \u043a\u0430\u043a\u0438\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u0443 \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0448 SSO. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u043c \u0435\u0433\u043e \u0441 \u043d\u0430\u0448\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0439.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435: <code>j-service<\/code>. \u041e\u043d \u0438 \u0431\u0443\u0434\u0435\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0438\u043c Resource Server. \u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 <code>j-sso<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f web \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u0430\u043b\u0435\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c OAuth2 Resource Server:<\/p>\n<p><strong>j-service\/pom.xml<\/strong><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">     \/\/ .....     &lt;dependencies>         &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-starter-oauth2-resource-server&lt;\/artifactId>             &lt;version>3.0.6&lt;\/version>         &lt;\/dependency>     &lt;\/dependencies> &lt;\/project>  <\/code><\/pre>\n<p>\u0412\u0435\u0441\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b <code>j-service<\/code> \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-2.1\/j-service\/pom.xml\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/servlet\/oauth2\/resource-server\/opaque-token.html\" rel=\"noopener noreferrer nofollow\">OAuth 2.0 Resource Server<\/a>. \u0421\u0440\u0430\u0437\u0443 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u0432 \u043d\u0430\u0448\u0435\u043c <code>j-sso<\/code> \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b opaque tokens. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b Opaque Token \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0448 <code>j-service<\/code>. \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e: \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0448 <code>application.yml<\/code> \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <code>spring.security.oauth2.resourceserver.opaquetoken.*<\/code> \u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0445, \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<p><strong>application.yml<\/strong><\/p>\n<pre><code class=\"yaml\">\/\/ .....  spring:   security:     oauth2:       resourceserver:         opaquetoken:           client-id: test-client           client-secret: test-client           introspection-uri: http:\/\/localhost:7777\/oauth2\/token-info <\/code><\/pre>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0449\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Spring Security (\u043e\u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043d\u0438\u0436\u0435). \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 <code>sessionManagement<\/code>. \u0422\u0430\u043a \u043a\u0430\u043a security \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 <code>Authorization<\/code> \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u0441 \u0442\u0438\u043f\u043e\u043c <code>Bearer<\/code>, \u0442\u043e \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 <code>HttpSession<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Spring Security \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043c\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0438 <code>STATELESS<\/code>, \u0447\u0442\u043e\u0431\u044b Spring Security \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b <code>HttpSession<\/code> \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0435\u0433\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f <code>SecurityContext<\/code>. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c <code>JSESSIONID<\/code> Cookie \u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0438 Security \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <code>HttpSessionSecurityContextRepository<\/code>, <code>SessionManagementFilter<\/code> \u0438 <code>RequestCacheFilter<\/code>.<\/p>\n<p><code><strong>ResourceServerConfig<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Configuration @EnableWebSecurity @RequiredArgsConstructor public class ResourceServerConfig {      @Bean     public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {         \/\/ \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u0435\u0441\u0441\u0438\u0439         http.sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))                 .authorizeHttpRequests(customizer -> {                     customizer.anyRequest().authenticated();                 });          \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 OAuth2 Resource Server \u0441 Opaque Token         http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::opaqueToken);         return http.build();     } } <\/code><\/pre>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 main \u043a\u043b\u0430\u0441\u0441 &#8212; <code>ResourceApplication<\/code> \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441\u043e \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u0438\u043c endpoint-\u043e\u043c &#8212; <code>\/test<\/code>. \u041a\u043e\u0434 \u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0430\u043d\u0430\u043b\u0435\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0445 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-2.1\/j-service\/src\/main\/java\/ru\/dlabs\/sas\/example\/jservice\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>.<\/p>\n<p>\u0421\u043e\u0431\u0435\u0440\u0451\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 <code>j-sso<\/code> \u0438 <code>j-service<\/code>. \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043d\u0438\u0436\u0435\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043c Access Token. \u041d\u0430\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u0432\u0430\u0436\u043d\u043e \u043a\u0430\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 grant type, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u044d\u0442\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u0439\u0434\u0451\u043c \u043f\u043e \u043f\u0443\u0442\u0438 \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u0441 grant type \u0440\u0430\u0432\u043d\u044b\u043c <code>client_credentials<\/code>.<\/p>\n<pre><code>curl --location --request POST 'http:\/\/localhost:7777\/oauth2\/token?grant_type=client_credentials' \\ --header 'Authorization: Basic dGVzdC1jbGllbnQ6dGVzdC1jbGllbnQ=' <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\/\u043e\u0442\u0432\u0435\u0442\u0430 \u0438\u0437 Postman<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\">\n<div><figcaption>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a <code>Authorization<\/code> \u0441 \u0442\u0438\u043f\u043e\u043c <code>Basic<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f base64 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430: <code>test-client:test-client<\/code>. \u042d\u0442\u043e \u043d\u0430\u0448\u0438 <code>clientId<\/code> \u0438 <code>clientSecret<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 <code>j-sso<\/code>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 endpoint \u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043b\u043e\u0433\u0438.<\/p>\n<figure class=\"\">\n<div><figcaption>\u041b\u043e\u0433\u0438 j-service<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u0448 <code>j-service<\/code>, \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0437\u0430\u043f\u0440\u043e\u0441. \u0414\u0430\u043b\u0435\u0435 \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 <code>HTTP POST http:\/\/localhost:7777\/oauth2\/token-info<\/code>. \u0412 \u043d\u0435\u0433\u043e \u043e\u043d \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442 \u0442\u043e\u0442 access \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u0441 \u043a\u043e\u0434\u043e\u043c <code>200 OK<\/code>. \u0418 \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 <code>java.lang.ClassCastException<\/code>. \u0418\u0442\u0430\u043a, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0449\u0430\u044e\u0442\u0441\u044f, \u043d\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 Introspection Endpoint \u043d\u0430\u0448\u0435\u0433\u043e <code>j-sso<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u043f\u043e\u0447\u0435\u043c\u0443.<\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0432 \u0433\u043b\u0430\u0432\u0443 <a href=\"https:\/\/habr.com\/ru\/articles\/737548\/\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Yandex \u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f<\/a>. \u0412 \u043a\u043e\u043d\u0446\u0435 \u044d\u0442\u043e\u0439 \u0433\u043b\u0430\u0432\u044b, \u043c\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 introspection endpoint, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 Spring. \u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 DTO \u043a\u043b\u0430\u0441\u0441, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u043d\u0435\u0446 \u043c\u0435\u0442\u043e\u0434\u0430 <code>introspectionResponse()<\/code> \u0432 <code>AuthorizationServerConfig<\/code>. \u041c\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u0430 Jackson2 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b\u0438 \u043d\u0430\u0448 <code>TokenInfoDto<\/code> \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u0435\u0433\u043e \u0432 <code>HttpResponse<\/code>.<\/p>\n<figure class=\"\">\n<div><figcaption>\u041c\u0435\u0442\u043e\u0434 introspectionResponse() \u043a\u043b\u0430\u0441\u0441\u0430 AuthorizationServerConfig<\/figcaption><\/div>\n<\/figure>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>SpringOpaqueTokenIntrospector<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 Introspection endpoint \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 <code>j-service<\/code>.<\/p>\n<figure class=\"\">\n<div><figcaption>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 claims \u0432 SpringOpaqueTokenIntrospector<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <code>SpringOpaqueTokenIntrospector<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 <code>Map&lt;String, Object> claims<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 JSON \u0444\u043e\u0440\u043c\u0430\u0442 <code>TokenInfoDto<\/code>. \u0418 \u0442\u0443\u0442 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438, Jackson \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u0442\u0438\u043f <code>Instant<\/code> \u043d\u0435 \u0432 \u0447\u0438\u0441\u043b\u043e, \u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443. \u0421\u0440\u0430\u0437\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043f\u043e\u043b\u044f\u0445 <code>nbf<\/code>, <code>exp<\/code>, <code>iat<\/code> \u044d\u0442\u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e <strong>\u0441\u0435\u043a\u0443\u043d\u0434<\/strong> \u043e\u0442 \u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0440\u0435\u043c\u0451\u043d. \u042d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u0430\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@JsonFormat<\/code> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c Jackson-\u0443 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>Instant<\/code> \u0432 \u0447\u0438\u0441\u043b\u043e, \u043d\u043e \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b \u043a\u0430\u043a \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0438\u0436\u0435:<\/p>\n<p><code><strong>TokenInfoDto.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">public class TokenInfoDto {     \/\/ ....      @JsonFormat(             without = {JsonFormat.Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS},             shape = JsonFormat.Shape.NUMBER_INT     )     private Instant nbf;      \/\/ ..... } <\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043d\u0430\u043c \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u043d\u0435 \u0432\u0438\u0436\u0443 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 <code>JsonSerializer<\/code> \u0434\u043b\u044f \u0442\u0438\u043f\u0430 <code>Instant<\/code> \u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@JsonSerialize<\/code> \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430\u0434 \u043d\u0430\u0448\u0438\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u0448 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p><code><strong>JsonInstantSerializer.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">public class JsonInstantSerializer extends JsonSerializer&lt;Instant> {      @Override     public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {         if (value != null) {             gen.writeNumber(value.getEpochSecond());         } else {             gen.writeNull();         }     } } <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043d\u0430\u0434 \u043f\u043e\u043b\u044f\u043c\u0438 \u0441 \u0442\u0438\u043f\u043e\u043c Instant \u0432 <code>TokenInfoDto<\/code>:<\/p>\n<details class=\"spoiler\">\n<summary>TokenInfoDto.java<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\"> @Getter @Setter @Builder public class TokenInfoDto {      private Boolean active;     private String sub;     private List&lt;String> aud;     @JsonSerialize(using = JsonInstantSerializer.class)     private Instant nbf;     private List&lt;String> scopes;     private URL iss;     @JsonSerialize(using = JsonInstantSerializer.class)     private Instant exp;     @JsonSerialize(using = JsonInstantSerializer.class)     private Instant iat;     private String jti;     private String clientId;     private String tokenType;      private Object<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-349961","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/349961","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=349961"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/349961\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=349961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=349961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=349961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}