{"id":347894,"date":"2023-05-25T15:02:42","date_gmt":"2023-05-25T15:02:42","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=347894"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=347894","title":{"rendered":"<span>\u0421\u0442\u0440\u043e\u0438\u043c \u0441\u0432\u043e\u0439 SSO \u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Spring Authorization Server<\/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<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041d\u0430 \u0434\u043d\u044f\u0445 \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u0434 \u0432\u0441\u0435 \u0441\u0432\u043e\u0438 pet-\u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 SSO \u0441\u0435\u0440\u0432\u0438\u0441, \u0434\u0430\u0431\u044b \u043d\u0435 \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439.<\/p>\n<blockquote>\n<p>\u0415\u0434\u0438\u043d\u044b\u0439 \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 (Single sign-on, SSO) \u2013 \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438,<br \/> \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0434\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u043d\u0430<br \/> \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0435\u0434\u0438\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/blockquote>\n<p>\u0412\u043e\u0437\u0438\u0442\u044c\u0441\u044f \u0441 \u044d\u0442\u0438\u043c \u043e\u0441\u043e\u0431\u043e \u0434\u043e\u043b\u0433\u043e \u043c\u043d\u0435 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c. \u0412\u0441\u0435 \u0442\u0430\u043a\u0438 \u044d\u0442\u043e \u0434\u043b\u044f pet-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0431\u043e\u0440 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043f\u0430\u043b \u043d\u0430 Keycloak, \u043a\u0430\u043a \u0441\u0430\u043c\u043e\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 SSO \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<blockquote>\n<p>Keycloak \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 single sign-on \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e<br \/> \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c, \u043d\u0430\u0446\u0435\u043b\u0435\u043d \u043d\u0430 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b.<\/p>\n<\/blockquote>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u0438 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u043a\u043e\u0432\u044b\u0440\u044f\u0432\u0448\u0438\u0441\u044c \u0441 \u043d\u0438\u043c, \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043c\u043d\u0435 \u043e\u043d \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442. \u042f \u043b\u044e\u0431\u043b\u044e \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u043b\u0435\u0433\u043a\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u0446\u0435\u043b\u0438 (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 pet-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0431\u044b\u0432\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b). \u042f \u043f\u0438\u0448\u0443 \u043d\u0430 Java \u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u044b Spring \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0438\u0445 \u0437\u0430\u0434\u0430\u0447. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0441\u043b\u0435 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 Keycloak \u0432\u044b\u0431\u043e\u0440 \u043f\u0430\u043b \u043d\u0430 Spring Security. \u041d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u044f \u0443\u0436\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b \u0441\u0435\u0440\u0432\u0435\u0440 SSO, \u043d\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Spring Boot 2 \u0438 Spring OAuth2, \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u043c\u043d\u0435 \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u043a\u0430\u043a \u043d\u0430 Spring Boot 3, \u0442\u0430\u043a \u0438 \u043d\u043e\u0432\u044b\u0439 Spring Authorization Server. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u0447\u0438\u0442\u0430\u0432 \u043f\u0430\u0440\u0443 \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430 \u0445\u0430\u0431\u0440\u0435 \u0438 \u0432\u043e\u043e\u0440\u0443\u0436\u0438\u0432\u0448\u0438\u0441\u044c \u0441\u0430\u043c\u044b\u043c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432 (\u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 Spring Authorization Server <code>1.0.2<\/code>, Spring Boot <code>3.0.6<\/code>), \u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043b \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e SSO \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u044f \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0447\u0442\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u0445 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 Spring Authorization Server, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438 \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e. \u0418\u0442\u0430\u043a, \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043e\u0442 \u0441\u043b\u043e\u0432 \u043a \u0434\u0435\u043b\u0443!<\/p>\n<h3>\u0426\u0435\u043b\u0438<\/h3>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0432\u043e\u0435\u0433\u043e SSO \u044f \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0441\u0435\u0431\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:<\/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<ol>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>Java 17<\/p>\n<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<\/ol>\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<ol>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<\/ol>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 1: \u0421\u0442\u0440\u043e\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 Spring Authorization Server<\/h3>\n<p>\u041f\u0440\u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0432 Spring Authorization Server \u044f \u0431\u044b\u043b \u043f\u043e\u0440\u0430\u0436\u0435\u043d, \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043b\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0438 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u0432\u044b \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442\u0435\u0441\u044c \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438 \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043c\u0435\u043b\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438, \u0442\u0430\u043c \u0441 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c\u044e 80% \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Maven \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u043d\u0430\u0448\u0435\u0433\u043e sso server, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e j-sso. \u042f \u0441\u0440\u0430\u0437\u0443 \u0441\u043e\u0437\u0434\u0430\u043c \u043c\u043d\u043e\u0433\u043e\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Maven, \u0447\u0442\u043e\u0431\u044b \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u043d\u0430\u0448 demo-\u043f\u0440\u043e\u0435\u043a\u0442. \u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Maven \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 Spring Boot \u0438 Spring Authorization Server. \u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0432\u0435\u0440\u0441\u0438\u044f Spring Boot <code>3.0.6<\/code>, \u0430 Spring Authorization Server <code>1.0.2<\/code>. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e <code>pom.xml<\/code> \u0444\u0430\u0439\u043b\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 pom.xml<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt; &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\"&gt;     &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;      &lt;groupId&gt;ru.dlabs&lt;\/groupId&gt;     &lt;artifactId&gt;spring-authorization-server-example&lt;\/artifactId&gt;     &lt;packaging&gt;pom&lt;\/packaging&gt;     &lt;version&gt;0.0.1&lt;\/version&gt;     &lt;name&gt;spring-authorization-server-example&lt;\/name&gt;      &lt;properties&gt;         &lt;java.version&gt;17&lt;\/java.version&gt;         &lt;maven.compiler.target&gt;17&lt;\/maven.compiler.target&gt;         &lt;maven.compiler.source&gt;17&lt;\/maven.compiler.source&gt;         &lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;          &lt;security-oauth2-server.version&gt;1.0.2&lt;\/security-oauth2-server.version&gt;     &lt;\/properties&gt;      &lt;parent&gt;         &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;         &lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;         &lt;version&gt;3.0.5&lt;\/version&gt;         &lt;relativePath\/&gt;     &lt;\/parent&gt;      &lt;modules&gt;         &lt;module&gt;j-sso&lt;\/module&gt;     &lt;\/modules&gt;      &lt;dependencyManagement&gt;         &lt;dependencies&gt;             &lt;dependency&gt;                 &lt;groupId&gt;org.springframework.security&lt;\/groupId&gt;                 &lt;artifactId&gt;spring-security-oauth2-authorization-server                 &lt;\/artifactId&gt;                 &lt;version&gt;${security-oauth2-server.version}&lt;\/version&gt;             &lt;\/dependency&gt;         &lt;\/dependencies&gt;     &lt;\/dependencyManagement&gt; &lt;\/project&gt; <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e j-sso \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u044b Spring Boot:<\/p>\n<ul>\n<li>\n<p>spring-boot-starter-security<\/p>\n<\/li>\n<li>\n<p>spring-boot-starter-web<\/p>\n<\/li>\n<li>\n<p>spring-boot-starter<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0430\u043c Spring Authorization Server. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u043a\u0430\u043a\u0430\u044f-\u043d\u0438\u0431\u0443\u0434\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u042f \u043b\u044e\u0431\u043b\u044e \u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c log4j2. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u043b\u043e\u0433\u0433\u0435\u0440 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c log4j2. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u043c \u0438\u0437 <code>spring-boot-starter<\/code> <code>spring-boot-starter-logging<\/code> \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c <code>spring-boot-starter-log4j2<\/code>. \u041d\u0443 \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c <code>lombok<\/code>, \u043a\u0443\u0434\u0430 \u0436\u0435 \u043c\u044b \u0431\u0435\u0437 \u043d\u0435\u0433\u043e)) \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u043f\u043e\u043b\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f <code>pom.xml<\/code> \u0434\u043b\u044f \u043c\u043e\u0434\u0443\u043b\u044f j-sso.<\/p>\n<details class=\"spoiler\">\n<summary>pom.xml \u043c\u043e\u0434\u0443\u043b\u044f j-sso<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt; &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\"&gt;     &lt;parent&gt;         &lt;artifactId&gt;spring-authorization-server-example&lt;\/artifactId&gt;         &lt;groupId&gt;ru.dlabs&lt;\/groupId&gt;         &lt;version&gt;0.0.1&lt;\/version&gt;     &lt;\/parent&gt;     &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;      &lt;artifactId&gt;j-sso&lt;\/artifactId&gt;      &lt;properties&gt;         &lt;maven.compiler.source&gt;17&lt;\/maven.compiler.source&gt;         &lt;maven.compiler.target&gt;17&lt;\/maven.compiler.target&gt;     &lt;\/properties&gt;      &lt;dependencies&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter&lt;\/artifactId&gt;             &lt;exclusions&gt;                 &lt;exclusion&gt;                     &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;                     &lt;artifactId&gt;spring-boot-starter-logging&lt;\/artifactId&gt;                 &lt;\/exclusion&gt;             &lt;\/exclusions&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-log4j2&lt;\/artifactId&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.security&lt;\/groupId&gt;             &lt;artifactId&gt;spring-security-oauth2-authorization-server&lt;\/artifactId&gt;         &lt;\/dependency&gt;          &lt;dependency&gt;             &lt;groupId&gt;org.projectlombok&lt;\/groupId&gt;             &lt;artifactId&gt;lombok&lt;\/artifactId&gt;             &lt;version&gt;${lombok.version}&lt;\/version&gt;             &lt;scope&gt;provided&lt;\/scope&gt;         &lt;\/dependency&gt;     &lt;\/dependencies&gt;      &lt;build&gt;         &lt;finalName&gt;${project.artifactId}&lt;\/finalName&gt;         &lt;plugins&gt;             &lt;plugin&gt;                 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;                 &lt;artifactId&gt;spring-boot-maven-plugin&lt;\/artifactId&gt;                 &lt;configuration&gt;                     &lt;finalName&gt;${project.name}&lt;\/finalName&gt;                 &lt;\/configuration&gt;             &lt;\/plugin&gt;         &lt;\/plugins&gt;     &lt;\/build&gt; &lt;\/project&gt; <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 SSO \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 (\u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430) \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043d\u0430\u0448\u0435\u0433\u043e Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0432\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><code>SecurityConfig.java<\/code> &#8212; \u0432 \u043d\u0435\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0434\u0443\u043b\u044f j-sso.<\/p>\n<\/li>\n<li>\n<p><code>AuthorizationServerConfig.java<\/code> &#8212; \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">import static org.springframework.security.config.Customizer.withDefaults;  @EnableWebSecurity @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         http.authorizeHttpRequests(authorize -&gt;                 authorize.anyRequest().authenticated()         );         return http.formLogin(withDefaults()).build();     }      @Bean     public UserDetailsService users() {         UserDetails user = User.builder()                 .username(\"admin\")                 .password(\"{noop}password\")                 .roles(\"USER\")                 .build();         return new InMemoryUserDetailsManager(user);     } } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0430\u043c\u0443\u044e \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0438\u043d <code>SecurityFilterChain<\/code> \u0432 \u043d\u0435\u043c \u0443\u043a\u0430\u0436\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0437\u0430\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u043e\u0434 \u0441\u0435\u043a\u0443\u0440\u0438\u0442\u0438, \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u0445\u043e\u0434\u0430, \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u0443\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0443\u043a\u0430\u0437\u0430\u0432 <code>Customizer.withDefaults()<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 DSL \u043c\u0435\u0442\u043e\u0434\u0430 <code>formLogin(...)<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0438\u043d <code>UserDetailsService<\/code> \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0432 \u043d\u0435\u043c in memory \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041e\u043d \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h4>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Authorization Server.<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>AuthorizationServerConfig<\/code>. \u0412 \u043d\u0451\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0438\u043d <code>SecurityFilterChain<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u0443\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c\u044e <code>spring-security-oauth2-authorization-server<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <code>OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f j-sso. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0438\u043d <code>registeredClientRepository<\/code>, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>RegisteredClientRepository<\/code>. \u042d\u0442\u043e\u0442 \u0431\u0438\u043d \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0435\u043c <code>InMemoryRegisteredClientRepository<\/code>, \u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u043e\u0437\u0434\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>RegisteredClientRepository<\/code>. \u0422\u0430\u043a, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u043c\u0435\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u0445.<\/p>\n<p><code><strong>AuthorizationServerConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class AuthorizationServerConfig {      private final AuthorizationServerProperties authorizationServerProperties;      @Bean     @Order(Ordered.HIGHEST_PRECEDENCE)     public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {         OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);         http.exceptionHandling(exceptions -&gt;                 exceptions.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint(\"\/login\"))         );         return http.build();     }      @Bean     public RegisteredClientRepository registeredClientRepository() {         return new InMemoryRegisteredClientRepository(                 RegisteredClient.withId(\"test-client-id\")                         .clientName(\"Test Client\")                         .clientId(\"test-client\")                         .clientSecret(\"{noop}test-client\")                         .redirectUri(\"http:\/\/localhost:5000\/code\")                         .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)                         .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)                         .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)                         .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)                         .build()         );     }      @Bean     public JWKSource&lt;SecurityContext&gt; jwkSource() {         RSAKey rsaKey = JwkUtils.generateRsa();         JWKSet jwkSet = new JWKSet(rsaKey);         return (jwkSelector, securityContext) -&gt; jwkSelector.select(jwkSet);     }      @Bean     public AuthorizationServerSettings authorizationServerSettings() {         return AuthorizationServerSettings.builder()                 .issuer(authorizationServerProperties.getIssuerUrl())                 .build();     } }  <\/code><\/pre>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0431\u0438\u043d\u0435 <code>registeredClientRepository<\/code> \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0423\u043a\u0430\u0436\u0435\u043c \u0435\u043c\u0443 client_id <code>test-client<\/code> \u0438 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 client_secret. PasswordEncoder \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. \u0423\u043a\u0430\u0436\u0435\u043c \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 grant types. \u0412 \u043c\u0435\u0442\u043e\u0434\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Basic Authentication &#8212; \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0439\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c Authorization \u0445\u0435\u0434\u0435\u0440 \u0441 \u0442\u0438\u043f\u043e\u043c Basic. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>redirectUri<\/code>, \u043e\u043d \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 authorization code flow, \u0442\u043e \u0435\u0441\u0442\u044c \u0434\u043b\u044f grant_type <code>AUTHORIZATION_CODE<\/code>. \u0412 \u044d\u0442\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043d\u0430 \u043a\u0430\u043a\u043e\u0439 URL \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u0430 \u0443 \u043d\u0430\u0441 JWT, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0442 \u043d\u0430\u0441 \u0442\u0430\u043a\u0436\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0431\u0438\u043d\u0430 <code>jwkSource<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 RSA \u043a\u043b\u044e\u0447\u0435\u0439. \u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 RSA \u043a\u043b\u044e\u0447\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 \u0441 \u043e\u0431\u0449\u0435\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0439, \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u044d\u0442\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 Utility \u043a\u043b\u0430\u0441\u0441 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <code>JwkUtils<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>JwkUtils.java<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">public class JwkUtils {      public static RSAKey generateRsa() {         KeyPair keyPair = generateRsaKey();         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();         return new RSAKey.Builder(publicKey)                 .privateKey(privateKey)                 .keyID(UUID.randomUUID().toString())                 .build();     }      public static KeyPair generateRsaKey() {         KeyPair keyPair;         try {             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(\"RSA\");             keyPairGenerator.initialize(2048);             keyPair = keyPairGenerator.generateKeyPair();         } catch (Exception ex) {             throw new IllegalStateException(ex);         }         return keyPair;     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0432\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c, \u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c <code>spring-security-oauth2-authorization-server<\/code> \u0442\u0430\u043a\u0436\u0435 \u0432 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u0438\u043d \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0430\u043c\u043e\u0433\u043e OAuth2 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0431\u0438\u043d <code>authorizationServerSettings<\/code> \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0432 \u043d\u0435\u043c \u043f\u043e\u043a\u0430 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>issuer<\/code> &#8212; \u044d\u0442\u043e \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 URL \u0430\u0434\u0440\u0435\u0441 \u043d\u0430\u0448\u0435\u0433\u043e SSO \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u042f \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u043b\u044e\u0431\u043b\u044e \u0442\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u043a\u043e\u0434\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u044d\u0442\u043e\u0442 URL \u0432 <code>application.yml<\/code> \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 \u043a\u043b\u0430\u0441\u0441 <code>AuthorizationServerProperties<\/code>. <code>AuthorizationServerProperties<\/code> &#8212; \u044d\u0442\u043e \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@ConfigurationProperties<\/code>, \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c \u0438\u0437 <code>application.yml<\/code> \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p><code><strong>AuthorizationServerProperties.class<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Setter @Getter @Configuration @ConfigurationProperties(prefix = \"spring.security.oauth2.authorizationserver\") public class AuthorizationServerProperties {      private String issuerUrl;     private String introspectionEndpoint; } <\/code><\/pre>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">server:     port: 7777  logging:     level:         root: DEBUG         org.apache.tomcat.util.net.NioEndpoint: ERROR         sun.rmi: ERROR         java.io: ERROR         javax.management: ERROR  spring:     application:         name: j-sso     security:         oauth2:             authorizationserver:                 issuer-url: http:\/\/localhost:7777 <\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448 j-sso. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0443 \u043d\u0430\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0444\u043e\u0440\u043c\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 \u0432 \u043d\u0430\u0448\u0435\u043c j-sso \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 <code>\/login<\/code>. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b OAuth2 Authorization Server \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u0441\u0435 3 \u0442\u0438\u043f\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f OAuth2 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/draft-ietf-oauth-v2-1-07#section-4.1\" rel=\"noopener noreferrer nofollow\">The OAuth 2.1 Authorization Framework<\/a>. \u0414\u0430, \u0432\u044b \u043d\u0435 \u043e\u0448\u0438\u0431\u043b\u0438\u0441\u044c, <code>spring-security-oauth2-authorization-server<\/code> \u0432\u0435\u0440\u0441\u0438\u0438 <code>1.x.x<\/code> \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e OAuth2.1, \u0430 \u043d\u0435 OAuth2.0. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043d\u0435 \u0438\u0449\u0438\u0442\u0435 \u0432 SSO password grant type, \u0435\u0433\u043e \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u0414\u0443\u043c\u0430\u044e, \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e password grant type \u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0435\u0451 \u0432 \u043d\u0430\u0448 j-sso, \u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044d\u0442\u043e\u0433\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c\u0441\u044f \u0442\u0435\u043c \u0447\u0442\u043e \u0435\u0441\u0442\u044c. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0448 j-sso.<\/p>\n<h4>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u043c authorization code flow:<\/h4>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 <code>\/authorization<\/code>:<\/p>\n<pre><code>curl --location --request GET 'http:\/\/localhost:7777\/oauth2\/authorize?response_type=code&amp;client_id=test-client&amp;redirect_uri=http:\/\/localhost:5000\/code' <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0412\u043e\u0442 \u0442\u0430\u043a \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u044b \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/dfa\/65f\/f8b\/dfa65ff8b4ace45389213bb466df2f0b.png\" alt=\"\u0417\u0430\u043f\u0440\u043e\u0441 authorization\" title=\"\u0417\u0430\u043f\u0440\u043e\u0441 authorization\" width=\"1200\"><\/p>\n<div><figcaption>\u0417\u0430\u043f\u0440\u043e\u0441 authorization<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043b\u043e\u0433\u0438\u043d\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u0432\u0432\u0435\u0434\u0435\u043c \u043b\u043e\u0433\u0438\u043d\/\u043f\u0430\u0440\u043e\u043b\u044c \u0438 \u043d\u0430\u0436\u043c\u0451\u043c <code>Sign In<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e15\/b3d\/31e\/e15b3d31eb5961421866a1dca0c1268f.png\" alt=\"\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Spring Security\" title=\"\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Spring Security\" width=\"1200\"><\/p>\n<div><figcaption>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Spring Security<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f POST \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/login<\/code>, \u0438 \u043d\u0430\u0441 \u043e\u043f\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u044d\u0442\u0430 \u043c\u0430\u0433\u0438\u044f, \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/b5f\/11f\/e25\/b5f11fe25a99e996bf80f914b1e95a24.png\" alt=\"POST \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\" title=\"POST \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\" width=\"1200\"><\/p>\n<div><figcaption>POST \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 authorization, \u0438 \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 <code>Location<\/code>\u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/df1\/89a\/9f4\/df189a9f427816fd59b6a7fc16be2491.png\" alt=\"\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 authorization\" title=\"\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 authorization\" width=\"1200\"><\/p>\n<div><figcaption>\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 authorization<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u043a\u043e\u0434\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u0411\u0435\u0440\u0451\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c <code>grant_type<\/code> \u0440\u0430\u0432\u043d\u044b\u043c <code>authorization_code<\/code> \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c <code>code<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>access<\/code> \u0438 <code>refresh<\/code> \u0442\u043e\u043a\u0435\u043d\u044b.<\/p>\n<pre><code> curl --location --request POST 'http:\/\/localhost:7777\/oauth2\/token?grant_type=authorization_code&amp;code=M6MsgrcmEa6eKlslkgDoS3mEOSuNoN827eLFUu6-k2Vi1v-xW17it7ojPC6QXbnjVsvCVCvfkIWNRq8kmMZBcPcre2R2N9AvNSxwLCMIiO0q4SRjWcoYrOFztvputvxS&amp;redirect_uri=http:\/\/localhost:5000\/code' \\ --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\/getpro\/habr\/post_images\/b72\/df6\/de1\/b72df6de14c301aa450d6a1ee634ab03.png\" alt=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e \u043a\u043e\u0434\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" title=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e \u043a\u043e\u0434\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" width=\"1200\"><\/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 \u043f\u043e \u043a\u043e\u0434\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \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: test-client:test-client. \u042d\u0442\u043e \u043d\u0430\u0448\u0438 clientId \u0438 clientSecret, \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 <code>RegisteredClient<\/code>.<\/p>\n<h4>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430:<\/h4>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code> curl --location --request POST 'http:\/\/localhost:7777\/oauth2\/token?grant_type=refresh_token&amp;refresh_token=W8jsk970AG8p9oYjJ_mlT0Fgf-VWjEemcmXW9hvvcvgj_D3Rc_yfrDu5Dxm4C6ccUP5sZQY6eAjQOSTOuSPln0dNkf-9nXC7UcAN084T1bfBsUHO05ICszNAy2Az4sai' \\ --header 'Authorization: Basic dGVzdC1jbGllbnQ6dGVzdC1jbGllbnQ='  <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a <code>Authorization<\/code>, \u043a\u0430\u043a \u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0432\u044b\u0448\u0435.<\/p>\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\/getpro\/habr\/post_images\/48f\/284\/882\/48f284882b1a4b3a0b9e6fcd1b261cf1.png\" alt=\"\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\" title=\"\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\" width=\"1200\"><\/p>\n<div><figcaption>\u041e\u0431\u043d\u043e\u0432\u043b\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<h4>Client Credentials \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f:<\/h4>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0441 grant_type \u0440\u0430\u0432\u043d\u044b\u043c client_credentials, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0438\u0436\u0435.<\/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\/getpro\/habr\/post_images\/f1b\/4d5\/f6e\/f1b4d5f6e27a78378f9aec9f5ad604b2.png\" alt=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 Client Credentials\" title=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 Client Credentials\" width=\"1200\"><\/p>\n<div><figcaption>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 Client Credentials<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e SSO \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f\u043c.<\/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-1\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 2: \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 Opaque token \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439, \u043d\u043e \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 Authorization Server, \u043e\u0442\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044f\u0441\u044c \u043e\u0442 \u043d\u0435\u0433\u043e, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0442\u043e\u0442 Authorization Server, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d. \u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u044b \u0441\u0442\u0430\u0432\u0438\u043b\u0438. \u041f\u0435\u0440\u0432\u044b\u043c \u043f\u0443\u043d\u043a\u0442\u043e\u043c \u0448\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0445 (opaque) \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e JWT.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 Opaque token \u043e\u0442 JWT \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0435\u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 JWT \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043a\u0435\u043c \u0443\u0433\u043e\u0434\u043d\u043e, \u0430 Opaque token \u043d\u0435\u0442. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e JWT \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u043c. \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0441\u0435\u0440\u0432\u0435\u0440\u0443, \u043a\u0440\u043e\u043c\u0435 \u043a\u043b\u044e\u0447\u0435\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0441 \u0432\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 \u043a \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043b\u0443\u0436\u0431\u0435.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u0438\u043d\u0443\u0442\u043a\u0430 \u0442\u0435\u043e\u0440\u0438\u0438 \u043e\u043a\u043e\u043d\u0447\u0435\u043d\u0430, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u044d\u0442\u043e. \u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043e\u043d\u0430 \u043d\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u043b \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0412 <a href=\"https:\/\/docs.spring.io\/spring-authorization-server\/docs\/current\/reference\/html\/core-model-components.html#oauth2-token-generator\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0441\u043a\u0430\u0437\u0430\u043d\u043e<\/a>, \u0447\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 enum <code>OAuth2TokenFormat<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u0432\u0430 \u0444\u043e\u0440\u043c\u0430\u0442\u0430<\/p>\n<ol>\n<li>\n<p><code>OAuth2TokenFormat.SELF_CONTAINED<\/code> &#8212; JWT \u0444\u043e\u0440\u043c\u0430\u0442<\/p>\n<\/li>\n<li>\n<p><code>OAuth2TokenFormat.REFERENCE<\/code>&#8212; Opaque \u0444\u043e\u0440\u043c\u0430\u0442<\/p>\n<\/li>\n<\/ol>\n<p>\u042d\u0442\u043e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435\/\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 <code>RegisteredClient<\/code> \u0447\u0435\u0440\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 <code>tokenSettings<\/code>. \u042d\u0442\u043e \u043f\u043e\u043b\u0435 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f <code>TokenSettings<\/code>, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d\u044b \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u041f\u043e \u043a\u043b\u0430\u0441\u0441\u0443, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0435\u0441\u0442\u044c, \u0442\u0440\u0443\u0434\u043d\u043e, \u043d\u043e \u0443 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0435\u0441\u0442\u044c <code>builder()<\/code> \u0430 \u0442\u0430\u043c \u0443\u0436\u0435 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u0432\u0441\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u043b\u0430 \u0431\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u0440\u043e \u044d\u0442\u043e \u043f\u043e\u043b\u0435 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u043e\u0447\u043a\u0430<\/p>\n<blockquote>\n<p>tokenSettings: The custom settings for the OAuth2 tokens issued to the client \u2013 for example, access\/refresh token time-to-live, reuse refresh tokens, and others.<\/p>\n<\/blockquote>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u043d\u0430\u0448\u0435\u0433\u043e <code>test-client<\/code>.<\/p>\n<p><code><strong>AuthorizationServerConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class AuthorizationServerConfig {      \/\/ .........      @Bean     public RegisteredClientRepository registeredClientRepository() {         return new InMemoryRegisteredClientRepository(                 RegisteredClient.withId(\"test-client-id\")                         .clientName(\"Test Client\")                         .clientId(\"test-client\")                         .clientSecret(\"{noop}test-client\")                         .redirectUri(\"http:\/\/127.0.0.1:8080\/code\")                         .scope(\"read.scope\")                         .scope(\"write.scope\")                         .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)                         .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)                         .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)                         .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)                         .tokenSettings(TokenSettings.builder()                                 .accessTokenFormat(OAuth2TokenFormat.REFERENCE)                                 .accessTokenTimeToLive(Duration.of(30, ChronoUnit.MINUTES))                                 .refreshTokenTimeToLive(Duration.of(120, ChronoUnit.MINUTES))                                 .reuseRefreshTokens(false)                                 .authorizationCodeTimeToLive(Duration.of(30, ChronoUnit.SECONDS))                                 .build())                         .build()         );     }      \/\/ TODO \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 OPAQUE \u0442\u043e\u043a\u0435\u043d\u043e\u0432     \/\/    @Bean     \/\/    public JWKSource&lt;SecurityContext&gt; jwkSource() {     \/\/        RSAKey rsaKey = JwkUtils.generateRsa();     \/\/        JWKSet jwkSet = new JWKSet(rsaKey);     \/\/        return (jwkSelector, securityContext) -&gt; jwkSelector.select(jwkSet);     \/\/    }      \/\/...............  } <\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0435\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043a\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0443 \u043d\u0430\u0441 \u0438\u043c\u0435\u044e\u0442\u0441\u044f:<\/p>\n<ol>\n<li>\n<p><code>accessTokenFormat()<\/code> &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442 access_token (JWT \u0438\u043b\u0438 Opaque)<\/p>\n<\/li>\n<li>\n<p><code>accessTokenTimeToLive()<\/code> &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u043d\u0430\u0448\u0435\u0433\u043e access_token<\/p>\n<\/li>\n<li>\n<p><code>refreshTokenTimeToLive()<\/code> &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 refresh_token<\/p>\n<\/li>\n<li>\n<p><code>reuseRefreshTokens()<\/code> &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e \u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c refresh_token \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0441\u0440\u043e\u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0435\u0449\u0435 \u043d\u0435 \u0438\u0441\u0442\u0435\u043a<\/p>\n<\/li>\n<li>\n<p><code>authorizationCodeTimeToLive()<\/code> &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 authorization code \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 Authorization Code Flow<\/p>\n<\/li>\n<li>\n<p><code>idTokenSignatureAlgorithm()<\/code> &#8212; \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u0432 OpenID Connect (OIDC)<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0438\u043c <code>test-client<\/code> Opaque token \u0432\u043c\u0435\u0441\u0442\u043e JWT. \u0422\u0430\u043a\u0436\u0435 \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 access token \u0440\u0430\u0432\u043d\u043e\u0435 30-\u0438 \u043c\u0438\u043d\u0443\u0442\u0430\u043c, \u0430 \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 refresh token \u0440\u0430\u0432\u043d\u043e\u0435 120 \u043c\u0438\u043d\u0443\u0442. \u0417\u0430\u043f\u0440\u0435\u0442\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c refresh token \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438 \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 authorization code \u0440\u0430\u0432\u043d\u043e\u0435 30 \u0441\u0435\u043a\u0443\u043d\u0434. \u0411\u0438\u043d <code>jwkSource<\/code> \u043d\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u043a\u0430\u043a \u0438 \u043a\u043b\u0430\u0441\u0441 <code>JwkUtils<\/code>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0445 \u0441\u043c\u0435\u043b\u043e \u0443\u0431\u0440\u0430\u0442\u044c.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0435\u0449\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Introspection Endpoint. \u041c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0438\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, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u044d\u0442\u0438\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OAuth2 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0434\u0435\u043b \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c [Token Introspection Endpoint (<a href=\"https:\/\/www.oauth.com\/oauth2-servers\/token-introspection-endpoint\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.oauth.com\/oauth2-servers\/token-introspection-endpoint\/<\/a>). \u0422\u0430\u043c \u043e\u043f\u0438\u0441\u0430\u043d \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u043c \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c\u0438. \u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Spring Authorization Server \u0438 \u043d\u0430\u0439\u0434\u0435\u043c \u0442\u0430\u043c \u0440\u0430\u0437\u0434\u0435\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/docs.spring.io\/spring-authorization-server\/docs\/current\/reference\/html\/protocol-endpoints.html#oauth2-token-introspection-endpoint\" rel=\"noopener noreferrer nofollow\">OAuth2 Token Introspection Endpoint<\/a>. \u0412 \u044d\u0442\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u044d\u0442\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041f\u043e\u043a\u0430 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043d\u043e \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043d\u0430\u043c \u044d\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f. \u0418\u0437\u043c\u0435\u043d\u0438\u043c \u043b\u0438\u0448\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c URL \u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0431\u0438\u043d\u0435 <code>authorizationServerSettings<\/code> \u0443\u043a\u0430\u0436\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c URL <code>tokenIntrospectionEndpoint(...)<\/code>. \u0422\u0430\u043a \u043a\u0430\u043a issue url \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432 \u0444\u0430\u0439\u043b <code>application.yml<\/code>, \u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441 \u043d\u0430\u0448\u0438\u043c introspection endpoint \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0442\u0430\u043a\u0436\u0435.<\/p>\n<p><code><strong>AuthorizationServerConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class AuthorizationServerConfig {      \/\/ ......      @Bean     public AuthorizationServerSettings authorizationServerSettings() {         return AuthorizationServerSettings.builder()                 .issuer(authorizationServerProperties.getIssuerUrl())                 .tokenIntrospectionEndpoint(authorizationServerProperties.getIntrospectionEndpoint())                 .build();     } } <\/code><\/pre>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code>server:     port: 7777  spring:     application:         name: j-sso     security:         oauth2:             authorizationserver:                 issuer-url: http:\/\/localhost:7777                 introspection-endpoint: \/oauth2\/token-info <\/code><\/pre>\n<p>\u0421\u043e\u0431\u0435\u0440\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 OAuth2. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0435 JWT \u0442\u043e\u043a\u0435\u043d\u044b, \u0430 \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b. \u041f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0443\u043d\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d.<\/p>\n<h4>\u041f\u043e\u0441\u0442\u0440\u043e\u0438\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f j-sso<\/h4>\n<p>\u041d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u0435\u0449\u0435 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u0447\u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c, \u0434\u0430 \u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0443\u0436\u0435 &#171;\u0440\u0443\u043a\u0430\u043c\u0438 \u043f\u043e\u0442\u0440\u043e\u0433\u0430\u0442\u044c&#187; \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c authorization code. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0432 \u043a\u043e\u043d\u0446\u0435 \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 VueJS \u043a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0448 j-sso \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043a\u0435\u043d\u0435. \u0414\u0443\u043c\u0430\u044e, \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c!<br \/> \u041f\u0440\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u043a\u0440\u0430\u0442\u0446\u0435, \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\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 VueJS, \u043f\u0440\u043e \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043e\u0440\u0435\u043d\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>test-client<\/code> &#8212; \u0432 \u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441\u0430\u043c\u043e VueJS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 vue-cli \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <a href=\"https:\/\/cli.vuejs.org\/guide\/creating-a-project.html#vue-create\" rel=\"noopener noreferrer nofollow\">\u0412\u043e\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>, \u0433\u0434\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f. Node.js \u044f \u0432\u0437\u044f\u043b \u0432\u0435\u0440\u0441\u0438\u0438 <code>16.17.0<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>package.json<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"json\">{     \"name\": \"test-client\",     \"version\": \"0.0.1\",     \"scripts\": {         \"serve\": \"vue-cli-service serve\",         \"build\": \"vue-cli-service build\"     },     \"dependencies\": {         \"core-js\": \"^3.8.3\",         \"vue\": \"^3.2.13\",         \"vue-router\": \"^4.0.3\",         \"vuex\": \"^4.0.0\",         \"axios\": \"^0.27.2\"     },     \"devDependencies\": {         \"@vue\/cli-plugin-babel\": \"~5.0.0\",         \"@vue\/cli-plugin-router\": \"~5.0.0\",         \"@vue\/cli-plugin-vuex\": \"~5.0.0\",         \"@vue\/cli-service\": \"~5.0.0\"     },     \"engines\": {         \"npm\": \"&gt;=8.0.0\",         \"node\": \"&gt;=16.0.0\"     },     \"browserslist\": [         \"&gt; 1%\",         \"last 2 versions\",         \"not dead\",         \"not ie 11\"     ] } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0423\u0434\u0430\u043b\u0438\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b:<\/p>\n<ol>\n<li>\n<p><code>login.vue<\/code> &#8212; \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0430 \u043d\u0435\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043a\u043d\u043e\u043f\u043a\u0443 Login, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 j-sso<\/p>\n<\/li>\n<li>\n<p><code>home.vue<\/code> &#8212; \u0434\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041d\u0430 \u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043a\u0435\u043d\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0438\u0436\u0435 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u044d\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b:<\/p>\n<details class=\"spoiler\">\n<summary>login.vue<\/summary>\n<div class=\"spoiler__content\">\n<pre><code> &lt;template&gt;     &lt;h1&gt;         LOGIN PAGE     &lt;\/h1&gt;     &lt;button @click=\"login\"&gt;         LOGIN     &lt;\/button&gt; &lt;\/template&gt;  &lt;script&gt; import LoginService from \"@\/services\/login-service\";  export default {     name: \"login\",     methods: {         login() {             return LoginService.login();         }     } } &lt;\/script&gt;  &lt;style scoped&gt;  &lt;\/style&gt; <\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>home.vue<\/summary>\n<div class=\"spoiler__content\">\n<pre><code> &lt;template&gt;     &lt;h1&gt;HOME PAGE&lt;\/h1&gt;     &lt;p aria-multiline=\"true\" aria-rowcount=\"20\"&gt;         {{ tokenInfoString }}     &lt;\/p&gt; &lt;\/template&gt;  &lt;script&gt;  import LoginService from \"@\/services\/login-service\";  export default {     name: \"home\",     data: () =&gt; {         return {             tokenInfo: {}         }     },     methods: {         getCurrentPrincipal() {             LoginService.getTokenInfo()                     .then(result =&gt; {                         console.log(\"Result getting token info: \", result);                         if (!result.data.active) {                             this.$router.replace({name: \"login\"});                             return;                         }                         this.tokenInfo = result.data;                     })                     .catch((err) =&gt; {                         console.log(\"Error getting token info: \", err);                         this.$router.replace({name: \"login\"});                     })         }     },     computed: {         tokenInfoString() {             if (!this.tokenInfo) {                 return null;             }             return JSON.stringify(this.tokenInfo, null, 8);         }     },     mounted() {         this.getCurrentPrincipal();     } } &lt;\/script&gt;  &lt;style scoped&gt;     p {         white-space: pre-wrap;         text-align: left;         margin-left: 20px;         font-size: 1.5em;     } &lt;\/style&gt; <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>login-service.js<\/code>, \u0432 \u043d\u0435\u043c \u043e\u043f\u0438\u0448\u0435\u043c \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u043e\u043a\u0435\u043d\u0435.<\/p>\n<p><code><strong>login-service.js<\/strong><\/code><\/p>\n<pre><code>import axios from \"axios\";  const serverUrl = process.env.VUE_APP_OAUTH_URL; axios.defaults.baseURL = serverUrl;  const clientId = process.env.VUE_APP_OAUTH_CLIENT_ID; const authHeaderValue = process.env.VUE_APP_OAUTH_AUTH_HEADER; const redirectUri = process.env.VUE_APP_OAUTH_REDIRECT_URI;  const ACCESS_TOKEN_KEY = \"access_token\";  export default {      \/\/ \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 j-sso     login() {         let requestParams = new URLSearchParams({             response_type: \"code\",             client_id: clientId,             redirect_uri: redirectUri,             scope: 'read.scope write.scope'         });         window.location = serverUrl + \"\/oauth2\/authorize?\" + requestParams;     },      \/\/ \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 access \u0438 refresh \u0442\u043e\u043a\u0435\u043d\u043e\u0432     getTokens(code) {         let payload = new FormData()         payload.append('grant_type', 'authorization_code')         payload.append('code', code)         payload.append('redirect_uri', redirectUri)         payload.append('client_id', clientId)          return axios.post('\/oauth2\/token', payload, {                     headers: {                         'Content-type': 'application\/url-form-encoded',                         'Authorization': authHeaderValue                     }                 }         ).then(response =&gt; {              \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b, \u043a\u043b\u0430\u0434\u0435\u043c access token \u0432 LocalStorage             console.log(\"Result getting tokens: \" + response.data)             window.sessionStorage.setItem(ACCESS_TOKEN_KEY, response.data[ACCESS_TOKEN_KEY]);         })     },      \/\/ \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u043e\u043a\u0435\u043d\u0435     getTokenInfo() {         let payload = new FormData();         \/\/ \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0438\u0437 LocalStorage \u043d\u0430\u0448 access token \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 `token`         payload.append('token', window.sessionStorage.getItem(ACCESS_TOKEN_KEY));          return axios.post('\/oauth2\/token-info', payload, {             headers: {                 'Authorization': authHeaderValue             }         });     } } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u044f \u0432\u044b\u043d\u0435\u0441 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0432 .env \u0444\u0430\u0439\u043b, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 <code>.env.development<\/code>.<\/p>\n<p><code><strong>.env.development<\/strong><\/code><\/p>\n<pre><code>VUE_APP_OAUTH_REDIRECT_URI=http:\/\/127.0.0.1:8080\/code VUE_APP_OAUTH_CLIENT_ID=test-client VUE_APP_OAUTH_AUTH_HEADER=Basic dGVzdC1jbGllbnQ6dGVzdC1jbGllbnQ= VUE_APP_OAUTH_URL=http:\/\/localhost:7777 <\/code><\/pre>\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>redirect_uri<\/code>. \u041e\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u0441 \u043e\u0434\u043d\u043e\u0438\u043c\u0451\u043d\u043d\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u0431\u0438\u043d\u0435 <code>registeredClientRepository()<\/code>.<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043b\u043e\u0433\u0438\u043d\u0430 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438, \u043d\u043e \u0432 <code>redirect_uri<\/code> \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c <code>\/code<\/code>, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u0414\u0430, \u0432\u0441\u0435 \u0432\u0435\u0440\u043d\u043e, \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u043a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u044e \u044d\u0442\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 <code>beforeEach<\/code> \u0445\u0443\u043a\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0440\u043e\u0443\u0442\u0435\u0440\u0430.<\/p>\n<p><code><strong>router\/index.js<\/strong><\/code><\/p>\n<pre><code>import {createRouter, createWebHistory} from 'vue-router' import Home from '..\/views\/home.vue' import Login from '..\/views\/login.vue' import LoginService from \"@\/services\/login-service\";  const routes = [     {         path: '\/',         name: 'home',         component: Home     },     {         path: '\/login',         name: 'login',         component: Login     } ]  const router = createRouter({     history: createWebHistory(process.env.BASE_URL),     routes });   router.beforeEach((to, from, next) =&gt; {      \/\/ \u0435\u0441\u043b\u0438 \u043f\u0443\u0442\u044c \u0440\u0430\u0432\u0435\u043d \/code, \u0442\u043e \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 code \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b, \u0438 \u043f\u043e\u0441\u043b\u0435 \u0438\u0445 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f     \/\/ \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443     if (to.path === '\/code' &amp;&amp; to.query.code != null) {         LoginService.getTokens(to.query.code).then(() =&gt; {             next({name: 'home'});         });     } else {         next()     } });  export default router <\/code><\/pre>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 \u0433\u043e\u0442\u043e\u0432. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c. \u041f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 <code>http:\/\/localhost:8080<\/code> \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043b\u043e\u0433\u0438\u043d\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 access token. \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 login, \u0443 \u043d\u0430\u0441 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 j-sso. \u0412\u0432\u043e\u0434\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u043d\u0430\u0448 test-client, \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0438\u0438&#8230; \u0443 \u043d\u0430\u0441 \u043e\u0448\u0438\u0431\u043a\u0430.<\/p>\n<blockquote>\n<p>Access to XMLHttpRequest at &#8216;<a href=\"http:\/\/localhost:7777\/oauth2\/token\" rel=\"noopener noreferrer nofollow\">http:\/\/localhost:7777\/oauth2\/token<\/a>&#8216; from origin &#8216;<a href=\"http:\/\/127.0.0.1:8080\" rel=\"noopener noreferrer nofollow\">http:\/\/127.0.0.1:8080<\/a>&#8216; has been blocked by CORS policy: Response to preflight request doesn&#8217;t pass access control check: Redirect is not allowed for a preflight request.<\/p>\n<\/blockquote>\n<p>\u041d\u0430\u0441 \u043d\u0435 \u043f\u0443\u0441\u043a\u0430\u044e\u0442 \u043d\u0430 j-sso, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u0434\u043e\u043c\u0435\u043d\u0435, \u0430 \u043c\u044b \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u0440\u043e\u0441\u0441-\u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u0417\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c CORS.<\/p>\n<blockquote>\n<p>Cross-origin resource sharing \u2014 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0434\u043e\u043c\u0435\u043d\u0430.<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430 \u043d\u0430\u0448\u0435\u043c j-sso \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>CORSConfig<\/code> \u0438 \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0432 \u043d\u0435\u043c \u0431\u0438\u043d <code>corsFilter<\/code>.<\/p>\n<p><code><strong>CORSConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @Configuration public class CORSConfig {      @Bean     public FilterRegistrationBean&lt;CorsFilter&gt; corsFilter() {         log.debug(\"CREATE CORS FILTER\");         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();         CorsConfiguration config = new CorsConfiguration();          config.setAllowCredentials(true);          \/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u043a\u0440\u043e\u0441\u0441-\u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b         config.addAllowedOrigin(\"http:\/\/127.0.0.1:8080,http:\/\/localhost:8080\");         config.addAllowedHeader(CorsConfiguration.ALL);         config.addExposedHeader(CorsConfiguration.ALL);         config.addAllowedMethod(CorsConfiguration.ALL);          source.registerCorsConfiguration(\"\/**\", config);         FilterRegistrationBean&lt;CorsFilter&gt; bean = new FilterRegistrationBean&lt;&gt;(new CorsFilter(source));         bean.setOrder(Ordered.HIGHEST_PRECEDENCE);         return bean;     } } <\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 j-sso \u0438 \u0437\u0430\u043d\u043e\u0432\u043e \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 test-client. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e j-sso. \u0412\u0432\u043e\u0434\u0438\u043c \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c, \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u043c\u0441\u044f. \u0415\u0441\u043b\u0438 \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043c\u044b \u0432\u0432\u0435\u043b\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435, \u0442\u043e \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043d\u0430 <code>http:\/\/localhost:8080\/code<\/code>, \u0438 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0448 authorization code. \u0414\u0430\u043b\u0435\u0435, \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c access token, \u0438 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 <code>http:\/\/localhost:8080\/<\/code>, \u0433\u0434\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043d\u0430\u0448\u0435\u043c access token. \u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c01\/04a\/bf4\/c0104abf40d9fcd6cabf8240b807c659.png\" alt=\"\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" title=\"\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" width=\"1200\"><\/p>\n<div><figcaption>\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 demo \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043a\u0443\u043d\u0435\u043c\u0441\u044f \u0432\u043e \u0432\u0441\u0435\u043b\u0435\u043d\u043d\u0443\u044e Spring \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0438\u0437\u043d\u0443\u0442\u0440\u0438.<\/p>\n<p>\u0412\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 GET \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430 \u043d\u0430 \u043d\u0430\u0448 j-sso. \u0412 \u043e\u0442\u0432\u0435\u0442 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u0442\u0443\u0441 302 \u0438 \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 <code>Location<\/code> \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430 j-sso.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/38a\/9b6\/0a4\/38a9b60a46430ecd1655c827c1604d78.png\" alt=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" title=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" width=\"1200\"><\/p>\n<div><figcaption>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, j-sso \u043f\u0440\u0438\u043d\u044f\u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u0438\u0434\u0438\u0442, \u0447\u0442\u043e \u0443 \u043d\u0435\u0433\u043e \u043d\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043b\u043e\u0433\u0438\u043d\u0430. \u041d\u043e \u044d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u0430\u0448 Security Filter Chain \u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u0436\u0435 \u0442\u0430\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p><code><strong>\u0421\u043f\u0438\u0441\u043e\u043a \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 Spring Security \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435<\/strong><\/code><\/p>\n<pre><code>Security filter chain: [         DisableEncodeUrlFilter         WebAsyncManagerIntegrationFilter         SecurityContextHolderFilter         HeaderWriterFilter         CsrfFilter         LogoutFilter         OAuth2AuthorizationRequestRedirectFilter         OAuth2LoginAuthenticationFilter         UsernamePasswordAuthenticationFilter         DefaultLoginPageGeneratingFilter         DefaultLogoutPageGeneratingFilter         RequestCacheAwareFilter         SecurityContextHolderAwareRequestFilter         AnonymousAuthenticationFilter         ExceptionTranslationFilter         AuthorizationFilter ] <\/code><\/pre>\n<p>\u0422\u0443\u0442 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u0432\u0441\u044f\u043a\u0438\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 3 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0442\u0430\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u0430\u044f Spring \u043c\u0430\u0433\u0438\u044f.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043a\u043b\u0430\u0441\u0441 AnonymousAuthenticationFilter \u0432 \u043c\u043e\u043c\u0435\u043d\u0442\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 AnonymousAuthenticationFilter<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d27\/6a6\/614\/d276a661463f47976259795f204e875e.png\" alt=\"\u041a\u043b\u0430\u0441\u0441 AnonymousAuthenticationFilter\" title=\"\u041a\u043b\u0430\u0441\u0441 AnonymousAuthenticationFilter\" width=\"1200\"><\/p>\n<div><figcaption>\u041a\u043b\u0430\u0441\u0441 AnonymousAuthenticationFilter<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p><code>AnonymousAuthenticationFilter<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 <code>AnonymousAuthenticationToken<\/code> \u0447\u0435\u0440\u0435\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 Supplier \u0432 <code>securityContextHolderStrategy<\/code>, \u043a\u0430\u043a \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f security \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430. \u0415\u0441\u043b\u0438 \u043c\u044b \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043c\u0435\u0442\u043e\u0434 <code>defaultWithAnonymous<\/code>, \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0432 \u043d\u0435\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0438 \u0435\u0441\u043b\u0438 \u043e\u043d \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f <code>AnonymousAuthenticationToken<\/code> \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 security context, \u043a\u0430\u043a \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 <code>ExceptionTranslationFilter<\/code> \u043f\u043e\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0434\u0430\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u043d\u043e \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u0432 \u0431\u043b\u043e\u043a\u0435 try catch.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/355\/12b\/429\/35512b429eca21ca1181ca0eafa62add.png\" alt=\"\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter\" title=\"\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter\" width=\"1200\"><\/p>\n<div><figcaption>\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432 \u0438\u0433\u0440\u0443 \u0432\u0441\u0442\u0443\u043f\u0430\u0435\u0442 <code>AuthorizationFilter<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 AuthorizationFilter<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/8f3\/ad8\/005\/8f3ad800584266b56f331df099351b5c.png\" alt=\"\u041a\u043b\u0430\u0441\u0441 AuthorizationFilter\" title=\"\u041a\u043b\u0430\u0441\u0441 AuthorizationFilter\" width=\"1200\"><\/p>\n<div><figcaption>\u041a\u043b\u0430\u0441\u0441 AuthorizationFilter<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043d \u0431\u0435\u0440\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 <code>securityContextHolderStrategy<\/code> \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u0437 \u043d\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0432 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0430\u0448 Supplier, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 <code>AnonymousAuthenticationFilter<\/code>. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <code>AnonymousAuthenticationToken<\/code>. \u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 authorizationManager \u043e\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0432\u044b\u043d\u043e\u0441\u0438\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 <code>AuthorizationDecision<\/code>, \u043a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u043e\u043d \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f <code>AccessDeniedException<\/code>.<\/p>\n<p>\u0418 \u0442\u0443\u0442 \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 <code>ExceptionTranslationFilter<\/code> \u0432 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 try catch, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043f\u0440\u043e\u0441\u0438\u043b \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter (\u0431\u043b\u043e\u043a catch)<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/48a\/bc9\/9a2\/48abc99a2e2ed7cf6cdeb298b448805e.png\" alt=\"\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter\" title=\"\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter\" width=\"1200\"><\/p>\n<div><figcaption>\u041a\u043b\u0430\u0441\u0441 ExceptionTranslationFilter<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0418 \u0432\u043e\u0442 \u0442\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u041e\u043d \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0434\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <code>handleAccessDeniedException<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f anonymous, \u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 \u0433\u043e\u0432\u043e\u0440\u044f\u0449\u0438\u0439 \u0441\u0430\u043c \u0437\u0430 \u0441\u0435\u0431\u044f <code>sendStartAuthentication<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>AuthenticationTrustResolverImpl<\/code>, \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0447\u0442\u043e \u043e\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043a\u043b\u0430\u0441\u0441\u0430 <code>AnonymousAuthenticationToken<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/7f2\/04b\/87b\/7f204b87b04faf5637229daaf7beae87.png\" alt=\"\u041c\u0435\u0442\u043e\u0434 handleAccessDeniedException \u043a\u043b\u0430\u0441\u0441\u0430 ExceptionTranslationFilter\" title=\"\u041c\u0435\u0442\u043e\u0434 handleAccessDeniedException \u043a\u043b\u0430\u0441\u0441\u0430 ExceptionTranslationFilter\" width=\"1200\"><\/p>\n<div><figcaption>\u041c\u0435\u0442\u043e\u0434 handleAccessDeniedException \u043a\u043b\u0430\u0441\u0441\u0430 ExceptionTranslationFilter<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0432 <code>sendStartAuthentication<\/code> \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443 <code>this.requestCache.saveRequest(request, response);<\/code>. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0439 \u043a \u043d\u0430\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0441\u044f \u0432 \u043a\u044d\u0448\u0435. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, Spring Security \u0432\u0438\u0434\u0438\u0442, \u0447\u0442\u043e \u0443 \u043d\u0435\u0433\u043e \u043d\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438, \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044f \u0435\u0433\u043e \u0432 \u043a\u044d\u0448, \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u043c\u0435\u0442\u043e\u0434 <code>commence()<\/code>, \u043e\u043d \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 <code>AuthenticationEntryPoint<\/code> \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0430 \u044d\u0442\u043e <code>LoginUrlAuthenticationEntryPoint<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438 \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043b\u043e\u0433\u0438\u043d\u0430.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/6a1\/8c3\/559\/6a18c3559229ebafc401d2c684f0e1ba.png\" alt=\"\u041c\u0435\u0442\u043e\u0434 sendStartAuthentication \u043a\u043b\u0430\u0441\u0441\u0430 ExceptionTranslationFilter\" title=\"\u041c\u0435\u0442\u043e\u0434 sendStartAuthentication \u043a\u043b\u0430\u0441\u0441\u0430 ExceptionTranslationFilter\" width=\"1200\"><\/p>\n<div><figcaption>\u041c\u0435\u0442\u043e\u0434 sendStartAuthentication \u043a\u043b\u0430\u0441\u0441\u0430 ExceptionTranslationFilter<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0430\u043a\u0438\u043c &#171;\u043d\u0435\u0437\u0430\u043c\u044b\u0441\u043b\u043e\u0432\u0430\u0442\u044b\u043c&#187; \u043f\u0443\u0442\u0435\u043c, \u0443 \u043d\u0430\u0441 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430. \u0412 \u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043a \u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 JSESSIONID \u043a\u0443\u043a\u0430, \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 request cache.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0432\u043e\u0434\u0438\u043c \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c, \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 <code>Sign In<\/code>. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f POST \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 endpoint <code>\/login<\/code>, \u0430 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0441 \u043a\u043e\u0434\u043e\u043c 302, \u0432 \u0445\u0435\u0434\u0435\u0440\u0435 <code>Location<\/code> \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043d\u0430\u0448 \u043f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/b5f\/11f\/e25\/b5f11fe25a99e996bf80f914b1e95a24.png\" alt=\"POST \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\" title=\"POST \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\" width=\"1200\"><\/p>\n<div><figcaption>POST \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0438\u0437 request cache \u043d\u0430\u0448 \u0437\u0430\u043f\u0440\u043e\u0441 &#171;\u043f\u0435\u0440\u0435\u043a\u043e\u0447\u0435\u0432\u0430\u043b&#187; \u0432 \u0445\u0435\u0434\u0435\u0440 <code>Location<\/code>, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 <code>SavedRequestAwareAuthenticationSuccessHandler<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 SavedRequestAwareAuthenticationSuccessHandler<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/58c\/a8f\/40e\/58ca8f40e1ff8d85f427f256d9881568.png\" alt=\"\u041a\u043b\u0430\u0441\u0441 SavedRequestAwareAuthenticationSuccessHandler\" title=\"\u041a\u043b\u0430\u0441\u0441 SavedRequestAwareAuthenticationSuccessHandler\" width=\"1200\"><\/p>\n<div><figcaption>\u041a\u043b\u0430\u0441\u0441 SavedRequestAwareAuthenticationSuccessHandler<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0418\u043c\u0435\u043d\u043d\u043e \u043e\u043d \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u0442\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438 \u0441\u0442\u0440\u043e\u0438\u0442 \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442. \u0422\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430, \u043c\u044b \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 request cache, \u0438 \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435 \u043f\u0443\u0441\u0442\u044b\u0435, \u0442\u043e \u043c\u044b ,\u0433\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043f\u0435\u0440\u0435\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441. \u0421\u0442\u043e\u0438\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0442\u043e\u0442 JSESSIONID, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043b\u043e\u0433\u0438\u043d\u0430, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u0432 request cache. \u041f\u043e \u043d\u0435\u043c\u0443 \u043c\u044b \u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0443\u0436\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, JSESSIONID \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u0414\u0430\u043b\u0435\u0435 \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u0431\u0435\u0440\u0435\u0442 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 access \u0438 refresh \u0442\u043e\u043a\u0435\u043d\u044b.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/df1\/89a\/9f4\/df189a9f427816fd59b6a7fc16be2491.png\" alt=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" title=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" width=\"1200\"><\/p>\n<div><figcaption>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043c \u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0439.<\/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\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 3: \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 Google \u0438 Github<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043d\u0430 \u043d\u0430\u0448\u0435\u043c j-sso \u0447\u0435\u0440\u0435\u0437 Google \u0438 Github, \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 &#171;Social Login&#187;. \u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 spring boot starter &#8212; <code>spring-boot-starter-oauth2-client<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432 \u043d\u0430\u0448 pom.xml \u0444\u0430\u0439\u043b<\/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\"?&gt; &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\"&gt;      \/\/.......      &lt;dependencies&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-oauth2-client&lt;\/artifactId&gt;         &lt;\/dependency&gt;     &lt;\/dependencies&gt;      \/\/.......  &lt;\/project&gt; <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043b\u0435\u0434\u0443\u044f <a href=\"https:\/\/spring.io\/guides\/tutorials\/spring-boot-oauth2\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0432\u0445\u043e\u0434 \u0447\u0435\u0440\u0435\u0437 Github. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u043d\u0430\u0448 <code>application.yml<\/code>.<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">\/\/ ...........  spring:     application:         name: j-sso     security:         oauth2:             authorizationserver:                 issuer-url: http:\/\/localhost:7777                 introspection-endpoint: \/oauth2\/token-info             client:                 registration:                     github:                         clientId: &lt;you_client_id&gt;                         clientSecret: &lt;you_client_secret&gt; <\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e oauth2 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f Github \u0438 \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0443 \u043d\u0435\u0433\u043e clientId \u0438 clientSecret. \u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043f\u0440\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e j-sso \u0432 Github.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/b87\/b3c\/b82\/b87b3cb821863915816796d31eee6d0f.png\" alt=\"\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 Github\" title=\"\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 Github\" width=\"800\"><\/p>\n<div><figcaption>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 Github<\/figcaption><\/div>\n<\/figure>\n<p><a href=\"https:\/\/docs.github.com\/ru\/apps\/oauth-apps\/building-oauth-apps\/creating-an-oauth-app\" rel=\"noopener noreferrer nofollow\">\u0412\u043e\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430<\/a>, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c OAuth \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 Github. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>Authorization callback URL<\/code>, \u0435\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u043d\u0438\u0436\u0435, \u044d\u0442\u043e\u0442 URL Spring \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u0440\u043e \u044d\u0442\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<blockquote>\n<p>The default redirect URI template is {baseUrl}\/login\/oauth2\/code\/{registrationId}. The registrationId is a unique<br \/> identifier for the ClientRegistration.<\/p>\n<\/blockquote>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u044d\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 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 <code>application.yml<\/code> \u0438 \u0432\u0443\u0430\u043b\u044f \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0439 URL \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043d\u0435\u0433\u043e.<\/p>\n<p>\u0421\u043e\u0431\u0435\u0440\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0443 \u043c\u0435\u043d\u044f.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/31d\/9eb\/354\/31d9eb35454d12fd05e41b9019325be9.gif\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Github\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Github\" width=\"1200\"><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Github<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Github, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f Google. \u041a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442 OAuth \u0432 Google \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 <a href=\"https:\/\/developers.google.com\/identity\/protocols\/oauth2?hl=ru\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0443 \u0432\u0430\u0441 \u043d\u0430 \u0444\u043e\u0440\u043c\u0435 \u043b\u043e\u0433\u0438\u043d\u0430 \u0432 \u0441\u0435\u043a\u0446\u0438\u0438 <strong>Login with OAuth 2.0<\/strong> \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043a\u043d\u043e\u043f\u043a\u0430 Google. \u0410 \u0440\u0430\u0437\u0434\u0435\u043b spring \u0432\u0430\u0448\u0435\u0433\u043e application.yml \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">\/\/ ....... spring:     application:         name: j-sso     security:         oauth2:             authorizationserver:                 issuer-url: http:\/\/localhost:7777                 introspection-endpoint: \/oauth2\/token-info             client:                 registration:                     github:                         clientId: &lt;your_github_client_id&gt;                         clientSecret: &lt;your_github_client_secret&gt;                      google:                         clientId: &lt;your_google_client_id&gt;                         clientSecret: &lt;your_google_client_secret&gt; <\/code><\/pre>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0430\u043a\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043f\u0443\u0442\u0451\u043c \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043d\u0430 j-sso \u0447\u0435\u0440\u0435\u0437 Github \u0438 Google. \u041d\u043e, \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0437\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \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 (Principal) \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0443 \u043d\u0430\u0441 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 security. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 Security Context \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c \u043b\u0435\u0436\u0438\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>Authentication<\/code>, \u0438 \u043a\u0430\u043a\u043e\u0439 \u0443 \u043d\u0435\u0433\u043e <code>Principal<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442. \u041e\u0431\u044a\u0435\u043a\u0442 <code>Authentication<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c &#8212; <code>SecurityContextHolder.getContext().getAuthentication()<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d81\/55b\/fd4\/d8155bfd47fdd6642db8e5735ba23a45.png\" alt=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0434 Github\" title=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0434 Github\" width=\"1200\"><\/p>\n<div><figcaption>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0434 Github<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0432\u044b\u0448\u0435, \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c Principal \u0443 \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>DefaultOAuth2User<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u043e\u0442 Github. \u0414\u0430\u043b\u0435\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0447\u0443\u0442\u044c \u043f\u043e \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u043c \u0442\u0435\u0441\u0442. \u0422\u0435\u043f\u0435\u0440\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0444\u043e\u0440\u043c\u044b \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 <code>Authentication<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/741\/e61\/7c7\/741e617c7edd2ecdcc5b672768e8c98f.png\" alt=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0434 \u0444\u043e\u0440\u043c\u0443\" title=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0434 \u0444\u043e\u0440\u043c\u0443\" width=\"1200\"><\/p>\n<div><figcaption>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0434 \u0444\u043e\u0440\u043c\u0443<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u0432\u0438\u0434\u0438\u043c \u0443\u0436\u0435 \u0434\u0440\u0443\u0433\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043b\u0430. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 <code>User<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0432 \u0431\u0438\u043d\u0435 <code>users<\/code> (\u043d\u0438\u0436\u0435 \u043e\u043d \u043f\u0440\u043e\u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d).<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u044d\u0442\u043e \u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u043d\u043e \u043c\u0435\u043d\u044f \u044d\u0442\u043e \u043d\u0435 \u0443\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435, \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u044f \u0441\u0442\u0430\u0432\u0438\u043b \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 PostgreSQL. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043a\u0430\u043a-\u0442\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e. \u0418 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 &#171;Social Login&#187; \u0443 \u043d\u0430\u0441 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0435\u0441\u043b\u0438 \u043e\u043d \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442. \u0418\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0431\u0443\u0434\u0435\u0442 \u0435\u0433\u043e email. \u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 in memory \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0432 \u0431\u0438\u043d\u0435 <code>users<\/code>.<\/p>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @EnableWebSecurity @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {     \/\/ .....      @Bean     public UserDetailsService users() {         UserDetails user = User.builder()                 .username(\"admin\")                 .password(\"{noop}password\")                 .roles(\"USER\")                 .build();         return new InMemoryUserDetailsManager(user);     }      \/\/ ..... }   <\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 \u043d\u0430\u0448\u0443 \u043d\u043e\u0432\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Google \u0438 Github. \u042f \u0441\u0440\u0430\u0437\u0443 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0441\u0435\u0439\u0447\u0430\u0441 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e <code>InMemoryUserDetailsManager<\/code> \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u0430\u043a \u043d\u0430\u0448. \u041c\u044b \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043b\u043e\u0436\u0438\u043c \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043e\u0441\u043d\u043e\u0432\u0443 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0421\u0423\u0411\u0414 PostgreSQL. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\n<p><code>UserEntity<\/code> &#8212; \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u0430\u0448\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435<\/p>\n<\/li>\n<li>\n<p><code>AuthorizedUser<\/code> &#8212; \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>User<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 Spring Security, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \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. \u0422\u043e \u0435\u0441\u0442\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>User<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>UserRepository<\/code> &#8212; \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f in memory \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c<\/p>\n<\/li>\n<li>\n<p><code>CustomUserDetailsService<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>UserDetailsService<\/code>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e Spring Security \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \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, \u043f\u043e \u0435\u0433\u043e username. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 username &#8212; \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 email.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <code>UserEntity<\/code>:<\/p>\n<p><code><strong>UserEntity.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class UserEntity {      private UUID id;     private String email;     private String passwordHash;     private String firstName;     private String secondName;     private String middleName;     private LocalDate birthday;     private String avatarUrl;     private Boolean active; }  <\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u0432\u0441\u0451 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u043d\u0451\u043c \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u0414\u0430\u043b\u0435\u0435 \u0441\u0440\u0430\u0437\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <code>UserRepository<\/code>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 <code>Map&lt;UUID, UserEntity&gt;<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u0440\u0438 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><code>UserEntity save(UserEntity entity)<\/code> &#8212; \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p><code>UserEntity findById(UUID id)<\/code> &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e ID<\/p>\n<\/li>\n<li>\n<p><code>UserEntity findByEmail(String email)<\/code> &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e email<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f c email <code>admin@example.com<\/code> \u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u043f\u0430\u0440\u043e\u043b\u0435\u043c \u0432 \u0445\u0443\u043a <code>afterPropertiesSet()<\/code>. \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0438\u0448\u044c \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0446\u0435\u043b\u044f\u0445, \u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u0435\u0449\u0430\u0435\u0442\u0441\u044f ?<\/p>\n<p><code><strong>UserRepository.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Repository public class UserRepository implements InitializingBean {      private final Map&lt;UUID, UserEntity&gt; store = new HashMap&lt;&gt;();      public UserEntity save(UserEntity entity) {         if (entity.getId() == null) {             entity.setId(UUID.randomUUID());         }         this.store.put(entity.getId(), entity);         return entity;     }      public UserEntity findById(UUID id) {         return this.store.getOrDefault(id, null);     }      public UserEntity findByEmail(String email) {         return this.store.values().stream()                 .filter(item -&gt; item.getEmail().equals(email))                 .findFirst()                 .orElse(null);     }       @Override     public void afterPropertiesSet() throws Exception {         this.save(UserEntity.builder()                 .email(\"admin@example.com\")                 .passwordHash(\"{noop}admin@example.com\")                 .active(true)                 .firstName(\"Admin\")                 .secondName(\"Admin\")                 .birthday(LocalDate.of(1998, 7, 14))                 .build());     } }  <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043d\u0430\u0448\u0435\u0433\u043e <code>AuthorizedUser<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e <code>User<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u043d\u0430\u043c Spring Security. \u041e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043b\u0430\u0441\u0441, \u0432 \u043d\u0435\u0433\u043e \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 <code>UserEntity<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0438\u0437 <code>User<\/code>. \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432 \u043d\u0451\u043c builder. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u0441\u043a\u0443\u0447\u043d\u044b\u0439 \u043a\u043e\u0434 <code>AuthorizedUserBuilder<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \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-3\/j-sso\/src\/main\/java\/ru\/dlabs\/sas\/example\/jsso\/dto\/AuthorizedUser.java\" rel=\"noopener noreferrer nofollow\">Github \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>.<\/p>\n<p><code><strong>AuthorizedUser.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter public class AuthorizedUser extends User {      private UUID id;     private String firstName;     private String secondName;     private String middleName;     private LocalDate birthday;     private String avatarUrl;      public AuthorizedUser(String username, String password, Collection&lt;? extends GrantedAuthority&gt; authorities) {         super(username, password, authorities);     }      public AuthorizedUser(             String username,             String password,             boolean enabled,             boolean accountNonExpired,             boolean credentialsNonExpired,             boolean accountNonLocked,             Collection&lt;? extends GrantedAuthority&gt; authorities     ) {         super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);     }      public static AuthorizedUserBuilder builder(String username, String password, Collection&lt;? extends GrantedAuthority&gt; authorities) {         return new AuthorizedUserBuilder(username, password, authorities);     }      public static AuthorizedUserBuilder builder(             String username,             String password,             boolean enabled,             boolean accountNonExpired,             boolean credentialsNonExpired,             boolean accountNonLocked,             Collection&lt;? extends GrantedAuthority&gt; authorities     ) {         return new AuthorizedUserBuilder(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);     }      public String getEmail() {         return this.getUsername();     }      \/\/ ....... }  <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 <code>UserDetailsService<\/code>\u0438 \u0443\u0431\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0439 \u0431\u0438\u043d <code>users<\/code>. <code>CustomUserDetailsService<\/code> \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u0432 \u043d\u0451\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434, \u044d\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0435\u0433\u043e username, \u043a\u043e\u0438\u043c \u0443 \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f email. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>UserRepository<\/code>. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0430\u0439\u0441 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Spring Security \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u043b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>UserDetailsService<\/code> \u0438 \u044f\u0432\u043b\u044f\u043b\u0441\u044f \u0431\u0438\u043d\u043e\u043c.<\/p>\n<p><code><strong>CustomUserDetailsService.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Service @RequiredArgsConstructor public class CustomUserDetailsService implements UserDetailsService {      private final UserRepository userRepository;      @Override     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {         UserEntity entity = userRepository.findByEmail(username);         if (entity == null) {             throw new UsernameNotFoundException(\"User with username = \" + username + \" not found\");         }         return AuthorizedUserMapper.map(entity, null);     } }  <\/code><\/pre>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0443 \u043d\u0430\u0441 \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c Principal \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 Spring Security \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0442\u0435\u043f\u0435\u0440\u044c <code>AuthorizedUser<\/code>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 social login. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Spring Security \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <code>OAuth2LoginConfigurer<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 DSL <code>oauth2Login(...)<\/code>. \u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u0438\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0432\u043e\u0439 <code>SocialConfigurer<\/code> \u043a\u043b\u0430\u0441\u0441 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0435\u0433\u043e. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0435\u0439\u0447\u0430\u0441 \u0432 <code>SecurityConfig<\/code> \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u043d\u043e \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u043d\u0444\u0438\u0433 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043c\u043e\u0442\u0440\u044f \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u0435, \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043b\u043e\u0436\u0438\u043c \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u0434\u043b\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0441\u043d\u043e\u0432\u0443.<\/p>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e <code>SocialConfigurer<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0438 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u0442 <code>AbstractHttpConfigurer<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0432 \u043d\u0451\u043c \u043c\u0435\u0442\u043e\u0434 <code>void init(HttpSecurity http)<\/code>. \u0412 \u044d\u0442\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e security. \u0414\u0430\u0432\u0430\u0439\u0442\u0435, \u0437\u0434\u0435\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0440\u0430\u0437\u0443 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f <code>AuthenticationSuccessHandler<\/code> \u0438 <code>AuthenticationFailureHandler<\/code>. \u041a\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e <code>SocialConfigurer<\/code> \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043d\u0438\u0436\u0435:<\/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&gt; {      private AuthenticationFailureHandler failureHandler;     private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();      @Override     public void init(HttpSecurity http) throws Exception {         http.oauth2Login(oauth2Login -&gt; {             if (this.successHandler != null) {                 oauth2Login.successHandler(this.successHandler);             }             if (this.failureHandler != null) {                 oauth2Login.failureHandler(this.failureHandler);             }         });     } } <\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0442 configurer \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e <code>SecurityConfig<\/code>, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u0430\u043d\u043d\u043e\u0433\u043e configurer \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 <code>http.apply(...)<\/code>.<\/p>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @EnableWebSecurity @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         SocialConfigurer socialConfigurer = new SocialConfigurer();         http.apply(socialConfigurer);          \/\/ .....     } }  <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a <a href=\"https:\/\/spring.io\/guides\/tutorials\/spring-boot-oauth2\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Spring OAuth2<\/a> \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0432 \u043d\u0435\u0439 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f \u043f\u0440\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0421\u0423\u0411\u0414 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0418 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<blockquote>\n<p>Implement and expose OAuth2UserService to call the Authorization Server as well as your database.<br \/> Your implementation can delegate to the default implementation, which will do the heavy lifting of calling the Authorization Server.<br \/> Your implementation should return something that extends your custom User object and implements OAuth2User.<\/p>\n<\/blockquote>\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 \u0441\u043e\u0437\u0434\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>OAuth2UserService<\/code>, \u0430 \u043d\u0430\u0448 Principal \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d \u043e\u0442 <code>User<\/code>, \u0438 \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>OAuth2User<\/code>. \u0427\u0443\u0442\u044c \u0432\u044b\u0448\u0435 \u043c\u044b \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 <code>AuthorizedUser<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d \u043e\u0442 <code>User<\/code>. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0436\u0435 \u043a\u043b\u0430\u0441\u0441\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>OAuth2User<\/code>. \u0418 \u043a\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e AuthorizedUser \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<p><code><strong>AuthorizedUser.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter public class AuthorizedUser extends User implements OAuth2User {      private UUID id;     private String firstName;     private String secondName;     private String middleName;     private LocalDate birthday;     private String avatarUrl;      private Map&lt;String, Object&gt; oauthAttributes;      \/\/ .....      @Override     public Map&lt;String, Object&gt; getAttributes() {         return oauthAttributes;     }      @Override     public String getName() {         return this.getUsername();     }      \/\/ ........   } <\/code><\/pre>\n<p>\u041d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>OAuth2UserService<\/code>. \u041c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0435\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0430 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e &#8212; <code>DefaultOAuth2UserService<\/code> \u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>OAuth2User loadUser(OAuth2UserRequest userRequest)<\/code>:<\/p>\n<p><code><strong>CustomOAuth2UserService.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Service @RequiredArgsConstructor public class CustomOAuth2UserService extends DefaultOAuth2UserService {      private final UserService userService;      @Override     public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {         OAuth2User oAuth2User = super.loadUser(userRequest);                            \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0434\u043e         String clientRegId = userRequest.getClientRegistration().getRegistrationId();   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 (google, github \u0438 \u0442.\u0434.)         AuthProvider provider = AuthProvider.fingByName(clientRegId);                   \/\/ \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c enum AuthProvider \u0438 \u043f\u043e \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435         return userService.saveAndMap(oAuth2User, provider);                            \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 UserService, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0438\u0448\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u0435\u0433\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0432 \u0411\u0414, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0430\u043f\u043f\u0438\u043d\u0433 \u043d\u0430 AuthorizedUser     } }  <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0438\u0437 \u043a\u043e\u0434\u0430 \u0432\u044b\u0448\u0435, \u043c\u044b \u0435\u0449\u0451 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:<\/p>\n<ol>\n<li>\n<p><code>enum AuthProvider<\/code> &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 enum \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 (google, github \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p><code>UserService<\/code> &#8212; \u044d\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e. \u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>OAuth2User<\/code>. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0432 \u0411\u0414 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e email. \u0418 \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u0430\u043f\u0438\u0442 \u043d\u0430\u0448\u0435\u0433\u043e UserEntity \u043d\u0430 AuthorizedUser.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 <code>DefaultUserService<\/code>, <code>AuthProvider<\/code> \u0438 \u0441\u043e\u043f\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432 \u043c\u043e\u0451\u043c <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-3\/j-sso\/src\/main\/java\/ru\/dlabs\/sas\/example\/jsso\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a><\/p>\n<details class=\"spoiler\">\n<summary>DefaultUserService.java<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\"> @Service @RequiredArgsConstructor public class DefaultUserService implements UserService {      private final UserRepository userRepository;      \/**      * \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f      *\/     @Override     public UserEntity save(OAuth2User userDto, AuthProvider provider) {         return switch (provider) {             case GITHUB -&gt; this.saveUserFromGithab(userDto);             case GOOGLE -&gt; this.saveUserFromGoogle(userDto);         };     }      \/**      * \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u043e\u043c \u0432 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c AuthorizedUser      *\/     @Override     public AuthorizedUser saveAndMap(OAuth2User userDto, AuthProvider provider) {         UserEntity entity = this.save(userDto, provider);         return AuthorizedUserMapper.map(entity, provider);     }       \/**      * \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\");           \/\/ \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442 email         if (email == null) {                                          \/\/ \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043d\u0435\u0442 \u0438\u043b\u0438 \u043e\u043d \u043f\u0443\u0441\u0442\u043e\u0439, \u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0435\u0442 email             throw new AuthException(AuthErrorCode.EMAIL_IS_EMPTY);         }         UserEntity user = this.userRepository.findByEmail(email);     \/\/ \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043f\u043e email         if (user == null) {                                           \/\/ \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0443 \u043d\u0430\u0441, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c UserEntity             user = new UserEntity();             user.setEmail(email);             user.setActive(true);                                     \/\/ \u043f\u043e\u043a\u0430 \u043f\u0443\u0441\u0442\u044c \u0432\u0441\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438         }          if (userDto.getAttribute(\"name\") != null) {             \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c firstName, lastName \u0438 middleName             String[] splitted = ((String) userDto.getAttribute(\"name\")).split(\" \");             user.setFirstName(splitted[0]);             if (splitted.length &gt; 1) {                 user.setSecondName(splitted[1]);             }             if (splitted.length &gt; 2) {                 user.setMiddleName(splitted[2]);             }         } else {                                                      \/\/ \u0438\u043d\u0430\u0447\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432 \u044d\u0442\u0438 \u043f\u043e\u043b\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 email             user.setFirstName(userDto.getAttribute(\"login\"));   \/\/ \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043d\u0430\u0434\u043e, \u0437\u0434\u0435\u0441\u044c \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438             user.setSecondName(userDto.getAttribute(\"login\"));         }          if (userDto.getAttribute(\"avatar_url\") != null) {       \/\/ \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0430\u0432\u0430\u0442\u0430\u0440, \u0442\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043f\u043e\u043b\u0435 avatarUrl             user.setAvatarUrl(userDto.getAttribute(\"avatar_url\"));         }         return userRepository.save(user);                             \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c UserEntity     }      \/**      * \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 Google      *\/     private UserEntity saveUserFromGoogle(OAuth2User userDto) {         \/\/ .....     } }  <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0438 \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448\u0438 j-sso \u0438 test-client. \u041f\u0440\u043e\u0439\u0434\u0451\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Github \u043d\u0430 j-sso. \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043d\u0430\u0448 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>Principal<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/6e2\/a4f\/123\/6e2a4f123632bbe681a71070a739f1ec.png\" alt=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Github\" title=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Github\" width=\"1200\"><\/p>\n<div><figcaption>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Authorization \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Github<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u0432\u0441\u0451, \u0447\u0442\u043e \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u044b\u0448\u0435, \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>Principal<\/code> \u0443 \u043d\u0430\u0441 <code>AuthorizedUser<\/code>. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432 \u044d\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 \u0432\u043d\u0435\u0434\u0440\u0438\u043c <code>UserRepository<\/code> \u0438 \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u043a \u043d\u0435\u043c\u0443 \u0432\u043d\u0443\u0442\u0440\u044c.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/2b0\/b25\/6fd\/2b0b256fd9d3fcfa47aaaffbb153d15c.png\" alt=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\" title=\"\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\" width=\"1200\"><\/p>\n<div><figcaption>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c, \u0442\u0430\u043c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0434\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0432\u044b\u0439, \u044d\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u043b\u0441\u044f \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Github<\/p>\n<\/li>\n<li>\n<p>\u0432\u0442\u043e\u0440\u043e\u0439, \u044d\u0442\u043e admin &#8212; \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u0445\u0443\u043a\u0435 <code>afterPropertiesSet()<\/code> \u043a\u043b\u0430\u0441\u0441\u0430 <code>DefaultUserRepository<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u0432\u0435\u0434\u0451\u043c \u0438\u0442\u043e\u0433 \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430. \u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 &#171;Social Login&#187; \u0447\u0435\u0440\u0435\u0437 Github \u0438 Google. \u041c\u044b \u0441\u043c\u043e\u0433\u043b\u0438 \u0443\u043d\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 Principal \u0432 Security Context. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0447\u0442\u043e \u043c\u043d\u0435 \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0438, \u0442\u0430\u043a \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0435\u0442 \u044f\u0432\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 Spring Security \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 User Services (<code>CustomOAuth2UserService<\/code>, <code>CustomUserDetailsService<\/code>). \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u044d\u0442\u043e ,\u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432 \u043d\u0438\u0445 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e, \u043e\u043d\u0430 \u0441\u043b\u043e\u0436\u043d\u0430\u044f,\u0430 \u0438\u0437\u043b\u0438\u0448\u043d\u0438\u0435 \u043d\u0435\u044f\u0432\u043d\u044b\u0435 \u0441\u0432\u044f\u0437\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u044d\u0442\u0438, \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u044f\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044f.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0436\u0435\u043c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Spring Security \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 services. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u0432 \u043d\u0430\u0448 <code>SocialConfigurer<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 <code>private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oAuth2UserService;<\/code>. \u0414\u0430\u043b\u0435\u0435, \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0430\u0439\u0441 \u043d\u0430\u0434\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 <code>UserInfoEndpointConfig<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c <code>oauth2Login.userInfoEndpoint().userService(this.oAuth2UserService);<\/code>. \u041a\u043e\u0434, \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u043e\u0433\u043e <code>SocialConfigurer<\/code> \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043d\u0438\u0436\u0435:<\/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&gt; {      private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oAuth2UserService;     private AuthenticationFailureHandler failureHandler;     private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();      @Override     public void init(HttpSecurity http) throws Exception {         http.oauth2Login(oauth2Login -&gt; {             if (this.oAuth2UserService != null) {                 oauth2Login.userInfoEndpoint().userService(this.oAuth2UserService);             }             if (this.successHandler != null) {                 oauth2Login.successHandler(this.successHandler);             }             if (this.failureHandler != null) {                 oauth2Login.failureHandler(this.failureHandler);             }         });     } } <\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u043d\u0430\u0448\u0435\u043c\u0443 <code>SecurityConfig<\/code>, \u0441\u0440\u0430\u0437\u0443 \u0432\u043d\u0435\u0434\u0440\u0438\u043c \u043d\u0430\u0448\u0438 <code>CustomOAuth2UserService<\/code> \u0438 <code>CustomUserDetailsService<\/code>. \u0421 \u043f\u0435\u0440\u0432\u044b\u043c \u0432\u0441\u0451 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 <code>socialConfigurer<\/code>, \u0430 \u0435\u0433\u043e \u043c\u044b \u0443\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438. \u041a\u0430\u043a \u0436\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <code>CustomUserDetailsService<\/code>? \u0412\u0435\u0434\u044c \u0435\u0433\u043e \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 AuthenticationProvider. \u0421\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0437\u0430\u043d\u043e\u0432\u043e \u0431\u0438\u043d AuthenticationProvider \u0438 AuthenticationManager, \u043c\u044b \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u043c \u043c\u043d\u043e\u0433\u043e \u0438\u0437\u043b\u0438\u0448\u043d\u0435\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448 <code>CustomUserDetailsService<\/code> \u0432 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 flow \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Spring Security. \u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @EnableWebSecurity(debug = true) @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {      private final CustomOAuth2UserService customOAuth2UserService;     private final CustomUserDetailsService userDetailService;      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         SocialConfigurer socialConfigurer = new SocialConfigurer()                 .oAuth2UserService(customOAuth2UserService);         http.apply(socialConfigurer);          http.getSharedObject(AuthenticationManagerBuilder.class)                 .userDetailsService(userDetailService);          http.authorizeHttpRequests(authorize -&gt;                 authorize.anyRequest().authenticated()         );         return http.formLogin(withDefaults()).build();     } }  <\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 <code>AuthenticationManagerBuilder<\/code> \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>http.getSharedObject(AuthenticationManagerBuilder.class)<\/code> \u0438 \u0432 \u043d\u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448 <code>CustomUserDetailsService<\/code>.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0432 j-sso \u0438 test-client, \u043c\u044b \u043f\u0440\u043e\u0439\u0434\u0451\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0438 \u0443\u0432\u0438\u0434\u0438\u043c \u0442\u043e\u0442 \u0436\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0447\u0442\u043e \u0438 \u043d\u0430 \u0433\u0438\u0444\u043a\u0435 \u0432\u044b\u0448\u0435. \u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u043e\u0442 \u0440\u0430\u0437\u0434\u0435\u043b \u043c\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u043c.<\/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-3\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 4: \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<\/h3>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0433\u043b\u0430\u0432\u0435 \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 &#171;Social Login&#187; \u0447\u0435\u0440\u0435\u0437 Github \u0438 Google. \u0412\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u043e \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e, \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 clientId \u0438 clientSecret. \u041d\u043e \u043a\u0430\u043a Spring \u043f\u043e\u043d\u044f\u043b, \u043a\u0443\u0434\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0438 \u043e\u0442\u043a\u0443\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\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? \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043c\u0430\u0433\u0438\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Yandex. \u0412 <a href=\"https:\/\/yandex.ru\/dev\/id\/doc\/ru\/register-client\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c OAuth \u043a\u043b\u0438\u0435\u043d\u0442 \u0432 Yandex (\u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0443 \u043d\u0438\u0445 \u0441\u0430\u043c\u044b\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0437\u0430 \u044d\u0442\u043e \u0440\u0435\u0441\u043f\u0435\u043a\u0442 Yandex-\u0443). \u041f\u043e\u0441\u043b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c clientId \u0438 clientSecret. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e \u0432\u0441\u0451 \u0432 <code>application.yml<\/code>.<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">spring:     application:         name: j-sso     security:         oauth2:             authorizationserver:                 issuer-url: http:\/\/localhost:7777                 introspection-endpoint: \/oauth2\/token-info             client:                 registration:                     github:                         clientId: &lt;your_github_client_id&gt;                         clientSecret: &lt;your_github_client_secret&gt;                      google:                         clientId: &lt;your_google_client_id&gt;                         clientSecret: &lt;your_google_client_secret&gt;                      yandex:                         clientId: &lt;your_yandex_client_id&gt;                         clientSecret: &lt;your_yandex_client_secret&gt; <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 j-sso \u0438 &#8230;. \u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<blockquote>\n<p>Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository]:<br \/> Factory method &#8216;clientRegistrationRepository&#8217; threw exception with message:<br \/> Provider ID must be specified for client registration &#8216;yandex&#8217;<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u0435\u0451 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438 \u0432\u0438\u0434\u0438\u043c \u0434\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u0430\u0433\u0438\u044f \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 \u043d\u0435 \u0432 Spring Security OAuth 2.0 Client. \u0414\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u0447\u0442\u043e \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c &#8216;yandex&#8217; \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440. \u041a\u0430\u043a \u0436\u0435 \u0442\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f? \u0414\u043b\u044f Google \u0438 Github \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0434\u043e \u0431\u044b\u043b\u043e, \u0430 \u0434\u043b\u044f Yandex \u043d\u0430\u0434\u043e? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432. \u0412 <code>OAuth2ClientProperties<\/code> \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>Registration<\/code>, \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u043d \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u0437 <code>application.yml<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 Registration<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/423\/01d\/78b\/42301d78b52ce78b8d45344ef0af42cc.png\" alt=\"\u041a\u043b\u0430\u0441\u0441 Registration\" title=\"\u041a\u043b\u0430\u0441\u0441 Registration\" width=\"1200\"><\/p>\n<div><figcaption>\u041a\u043b\u0430\u0441\u0441 Registration<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u0432\u0435\u0440\u0445\u0443 \u043a\u0440\u0430\u0441\u0443\u0435\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>provider<\/code>, \u0430 \u043d\u0430\u0434 \u043d\u0438\u043c \u0435\u0441\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u044b \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>google<\/p>\n<\/li>\n<li>\n<p>github<\/p>\n<\/li>\n<li>\n<p>facebook<\/p>\n<\/li>\n<li>\n<p>okta<\/p>\n<\/li>\n<\/ul>\n<p>\u042f\u043d\u0434\u0435\u043a\u0441\u0430 \u0432 \u044d\u0442\u043e\u043c \u0441\u043f\u0438\u0441\u043a\u0435 \u043d\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440. \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c <code>registration<\/code>, \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>provider<\/code>, \u0435\u0433\u043e \u0442\u043e \u043d\u0430\u043c \u0438 \u043d\u0430\u0434\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c. \u0412\u0441\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0438\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u0438\u0445 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c application.yml<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">  security:       oauth2:           authorizationserver:               issuer-url: http:\/\/localhost:7777               introspection-endpoint: \/oauth2\/token-info           client:               registration:                   github:                       clientId: &lt;your_github_client_id&gt;                       clientSecret: &lt;your_github_client_secret&gt;                    google:                       clientId: &lt;your_google_client_id&gt;                       clientSecret: &lt;your_google_client_secret&gt;                    yandex:                       provider: yandex                       clientId: &lt;your_yandex_client_id&gt;                       clientSecret: &lt;your_yandex_client_secret&gt;                       redirect-uri: http:\/\/localhost:7777\/login\/oauth2\/code\/yandex                       authorizationGrantType: authorization_code                       clientName: Yandex                provider:                   yandex:                       authorization-uri: https:\/\/oauth.yandex.ru\/authorize                       token-uri: https:\/\/oauth.yandex.ru\/token                       user-name-attribute: default_email                       userInfoUri: https:\/\/login.yandex.ru\/info <\/code><\/pre>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0434\u043b\u044f Yandex, \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0421\u0430\u043c\u044b\u0439 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445, \u044d\u0442\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 <code>provider<\/code>, \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0435\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 j-sso, \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0440\u043e\u0439\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Yandex. \u0415\u0441\u043b\u0438 \u043c\u044b \u0432\u0441\u0451 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438, \u0442\u043e \u0443 \u043d\u0430\u0441 \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 Yandex, \u0430 \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0441 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u0432 \u043d\u0430\u0448 j-sso, \u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443. \u041f\u043e\u0447\u0435\u043c\u0443? \u0414\u0430 \u0432\u0441\u0451 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u0431\u044b\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 <code>enum AuthProvider<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 Yandex \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 <code>DefaultUserService<\/code>. \u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0437\u0434\u0435\u0441\u044c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u0434, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0435\u0433\u043e \u0432 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-4\/j-sso\/src\/main\/java\/ru\/dlabs\/sas\/example\/jsso\/service\/DefaultUserService.java\" rel=\"noopener noreferrer nofollow\">Github \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>. \u041f\u043e\u0441\u043b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u0438\u0445 \u043c\u0435\u043b\u043e\u0447\u0435\u0439, \u0437\u0430\u043d\u043e\u0432\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441, \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c test-client \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Yandex.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/dlabs71\/spring-authorization-server-example\/chapter-4\/article-images\/chapter4\/oauth_yandex.gif\" alt=\"\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432\u0445\u043e\u0434\u0430 \u0447\u0435\u0440\u0435\u0437 Yandex\" title=\"\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432\u0445\u043e\u0434\u0430 \u0447\u0435\u0440\u0435\u0437 Yandex\" width=\"1200\"><\/p>\n<div><figcaption>\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432\u0445\u043e\u0434\u0430 \u0447\u0435\u0440\u0435\u0437 Yandex<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u0432\u0441\u0451 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e. \u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Yandex \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435. \u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u043e\u0435 \u0438 \u0432\u0442\u043e\u0440\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435: \u043f\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<p>\u0421\u0440\u0430\u0437\u0443 \u043d\u0430\u0437\u0440\u0435\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441, \u0430 \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438 \u0433\u0434\u0435? \u041f\u043e \u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443, \u0443 \u043d\u0430\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 <code>Resource Server<\/code> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e access token \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0431\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e. \u042d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439, \u043d\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u0443 \u043d\u0430\u0441 \u0441\u0442\u043e\u0438\u0442 \u0434\u0440\u0443\u0433\u043e\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u044f\u044f \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0430 SSO. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0432 \u043d\u0430\u0448\u0435\u043c j-sso, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>\/user\/current<\/code>. \u0415\u0441\u043b\u0438 \u043c\u044b \u043d\u0430 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0438\u0448\u044c \u0441 <code>access_token<\/code>, \u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 401 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438\u0437-\u0437\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438. \u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0430\u0448 j-sso \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0432 <code>SecurityConfig<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 JSESSIONID \u043a\u0443\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043d\u0430 j-sso \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0435\u0451 \u0438\u043c\u0435\u0442\u044c. \u041d\u043e \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043b\u043e\u0436\u0438\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e OAuth2. \u0427\u0442\u043e \u0436\u0435 \u0442\u043e\u0433\u0434\u0430 \u0434\u0435\u043b\u0430\u0442\u044c? \u0421\u0440\u0430\u0437\u0443 \u043d\u0430 \u0443\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432 j-sso <code>Resource Server<\/code> \u0441 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 security. \u041d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u0440\u0435\u0442\u044c\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0432 \u043d\u0430\u0448\u0435\u043c SSO \u0441\u0435\u0440\u0432\u0438\u0441\u0435, \u043a\u0430\u043a-\u0442\u043e \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u043e \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0441\u044f. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430 \u0443\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c introspection endpoint, \u0438 \u043f\u0443\u0442\u044c \u043e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442:<\/p>\n<ol>\n<li>\n<p>\u0444\u043b\u0430\u0433 active &#8212; \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u0430\u043a\u0442\u0438\u0432\u0435\u043d \u0438\u043b\u0438 \u043d\u0435\u0442. \u0415\u0441\u043b\u0438 true, \u0442\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u043e\u0431\u044a\u0435\u043a\u0442 Principal &#8212; \u043e\u0431\u044a\u0435\u043a\u0442 \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, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0438 \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c<\/p>\n<\/li>\n<li>\n<p>\u0441\u043f\u0438\u0441\u043e\u043a authorities &#8212; \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e<\/p>\n<\/li>\n<\/ol>\n<p>\u0418 \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u044f \u0431\u044b \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>access_token<\/code>. \u041d\u0430\u043c \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0434\u043e \u0435\u0433\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 introspection endpoint. \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0435\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0430\u043a\u0442\u0438\u0432\u0435\u043d:<\/p>\n<pre><code class=\"json\">{     \"active\": true,     \"sub\": \"admin@example.com\",     \"aud\": [         \"test-client\"     ],     \"nbf\": 1684683990,     \"scope\": \"write.scope read.scope\",     \"iss\": \"http:\/\/localhost:7777\",     \"exp\": 1684685790,     \"iat\": 1684683990,     \"jti\": \"4e9759cc-b80a-4cd2-840c-e5f666f1c499\",     \"client_id\": \"test-client\",     \"token_type\": \"Bearer\" } <\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435, \u043d\u0430 \u0440\u044f\u0434\u0443 \u0441 \u044d\u0442\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442 <code>TokenInfoDto<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442.<\/p>\n<p><code><strong>TokenInfoDto.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Getter @Setter @Builder public class TokenInfoDto {      private Boolean active;     private String sub;     private List&lt;String&gt; aud;     private Instant nbf;     private List&lt;String&gt; scopes;     private URL iss;     private Instant exp;     private Instant iat;     private String jti;     private String clientId;     private String tokenType;      private Object principal;     private Collection&lt;? extends GrantedAuthority&gt; authorities;  } <\/code><\/pre>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 introspection endpoint. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Authorization Server <code>OAuth2AuthorizationServerConfigurer<\/code> \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c DSL \u043c\u0435\u0442\u043e\u0434 <code>tokenIntrospectionEndpoint(...)<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 <code>introspectionResponseHandler<\/code>. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0432\u0441\u0451 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e <code>OAuth2AuthorizationServerConfigurer<\/code>. \u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u0438\u0437\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u0439 Security Filter Chain \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>AuthorizationServerConfig<\/code>:<\/p>\n<p><code><strong>AuthorizationServerConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class AuthorizationServerConfig {      \/\/ .....      @Bean     @Order(Ordered.HIGHEST_PRECEDENCE)     public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {         OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();         authorizationServerConfigurer.tokenIntrospectionEndpoint((config) -&gt; {             config.introspectionResponseHandler(this::introspectionResponse);         });          RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();         http.securityMatcher(endpointsMatcher)                 .authorizeHttpRequests(authorize -&gt; authorize.anyRequest().authenticated())                 .csrf(csrf -&gt; csrf.ignoringRequestMatchers(endpointsMatcher))                 .exceptionHandling(exceptions -&gt; exceptions.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint(\"\/login\")))                 .apply(authorizationServerConfigurer);         return http.build();     }      \/\/ .....  } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u043c\u0435\u0442\u043e\u0434-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a <code>introspectionResponse<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043d\u0438\u0436\u0435:<\/p>\n<p><code><strong>AuthorizationServerConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class AuthorizationServerConfig {      private final static String principalAttributeKey = \"java.security.Principal\";      private final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;     private final AuthorizationServerProperties authorizationServerProperties;     private final OAuth2AuthorizationService oAuth2AuthorizationService;      \/\/ .....      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());               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) {                     tokenInfoDtoBuilder                                                                                     \/\/ \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 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 TokenInfoDto                             .principal(attributeAuth.getPrincipal())                             .authorities(authentication.getAuthorities());                 }             }         }          ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);         mappingJackson2HttpMessageConverter.write(tokenInfoDtoBuilder.build(), null, httpResponse);                         \/\/ \u041f\u0440\u0435\u0434\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<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0430\u0441 Spring \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442 \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0431\u0438\u043d OAuth2AuthorizationService. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>ConfigUtilities<\/code> \u0438 \u0432 \u043d\u0451\u043c \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0435\u0433\u043e. \u0412\u043e\u0437\u043c\u0435\u043c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>InMemoryOAuth2AuthorizationService<\/code>.<\/p>\n<p><code><strong>ConfigUtilities.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Configuration(proxyBeanMethods = false) public class ConfigUtilities {      @Bean     public OAuth2AuthorizationService oAuth2AuthorizationService() {         return new InMemoryOAuth2AuthorizationService();     }  } <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c. \u041f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u043d\u0430\u0448 test-client \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 access token:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/ca7\/016\/af6\/ca7016af6afcc6f83f070aa2d615805a.png\" alt=\"\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\" title=\"\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\" width=\"1200\"><\/p>\n<div><figcaption>\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043a\u0435\u043d\u0435 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435<\/figcaption><\/div>\n<\/figure>\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-4\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0435\u0437\u044e\u043c\u0435<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 SSO \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Spring Security \u0438 Spring Authorization Server. \u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0432\u0445\u043e\u0434 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 authorization code flow. \u041d\u0430\u0447\u0430\u043b\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 SSO-\u0441\u0435\u0440\u0432\u0438\u0441, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 &#171;Social login&#187; \u0447\u0435\u0440\u0435\u0437 Google, Github \u0438 Yandex. \u0423\u0432\u0438\u0434\u0435\u043b\u0438 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u044b. \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438:<\/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<ol>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>Java 17<\/p>\n<\/li>\n<\/ol>\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<ol>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/p>\n<\/li>\n<li>\n<p>\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<\/li>\n<\/ol>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c, \u043a\u0430\u043a \u0432\u043a\u0440\u0443\u0442\u0438\u0442\u044c SPA VueJS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0444\u043e\u0440\u043c\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 SSO. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c PostgreSQL \u0438 Redis. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c springdoc (Swagger) \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435.<\/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>\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/draft-ietf-oauth-v2-1-07\" rel=\"noopener noreferrer nofollow\">The OAuth 2.1 Authorization Framework<\/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-authorization-server\/docs\/current\/reference\/html\/index.html\" rel=\"noopener noreferrer nofollow\">Spring Authorization Server<\/a><\/p>\n<\/li>\n<li>\n<p>\u0420\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 OAuth2.0 <a href=\"https:\/\/www.oauth.com\/\" rel=\"noopener noreferrer nofollow\">OAuth 2.0 Simplified<\/a><\/p>\n<\/li>\n<li>\n<p>\u0413\u0430\u0439\u0434 \u043f\u043e <a href=\"https:\/\/vuejs.org\/guide\/quick-start.html\" rel=\"noopener noreferrer nofollow\">VueJS<\/a><\/p>\n<\/li>\n<li>\n<p>\u0413\u0430\u0439\u0434 \u043f\u043e <a href=\"https:\/\/cli.vuejs.org\/guide\/creating-a-project.html#vue-create\" rel=\"noopener noreferrer nofollow\">Vue Cli<\/a><\/p>\n<\/li>\n<li>\n<p>\u0413\u0430\u0439\u0434 \u043f\u043e <a href=\"https:\/\/spring.io\/guides\/tutorials\/spring-boot-oauth2\/\" rel=\"noopener noreferrer nofollow\">Spring Security OAuth 2.0 Client<\/a><\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f OAuth2 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <a href=\"https:\/\/docs.github.com\/ru\/apps\/oauth-apps\/building-oauth-apps\/creating-an-oauth-app\" rel=\"noopener noreferrer nofollow\">Github<\/a><\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f OAuth2 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <a href=\"https:\/\/developers.google.com\/identity\/protocols\/oauth2?hl=ru\" rel=\"noopener noreferrer nofollow\">Google<\/a><\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f OAuth2 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <a href=\"https:\/\/yandex.ru\/dev\/id\/doc\/ru\/register-client\" rel=\"noopener noreferrer nofollow\">Yandex<\/a><\/p>\n<\/li>\n<\/ol>\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\/737548\/\"> https:\/\/habr.com\/ru\/articles\/737548\/<\/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<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041d\u0430 \u0434\u043d\u044f\u0445 \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u0434 \u0432\u0441\u0435 \u0441\u0432\u043e\u0438 pet-\u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 SSO \u0441\u0435\u0440\u0432\u0438\u0441, \u0434\u0430\u0431\u044b \u043d\u0435 \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439.<\/p>\n<blockquote>\n<p>\u0415\u0434\u0438\u043d\u044b\u0439 \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 (Single sign-on, SSO) \u2013 \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438,<br \/> \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0434\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u043d\u0430<br \/> \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0435\u0434\u0438\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/blockquote>\n<p>\u0412\u043e\u0437\u0438\u0442\u044c\u0441\u044f \u0441 \u044d\u0442\u0438\u043c \u043e\u0441\u043e\u0431\u043e \u0434\u043e\u043b\u0433\u043e \u043c\u043d\u0435 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c. \u0412\u0441\u0435 \u0442\u0430\u043a\u0438 \u044d\u0442\u043e \u0434\u043b\u044f pet-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0431\u043e\u0440 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043f\u0430\u043b \u043d\u0430 Keycloak, \u043a\u0430\u043a \u0441\u0430\u043c\u043e\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 SSO \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<blockquote>\n<p>Keycloak \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 single sign-on \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e<br \/> \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c, \u043d\u0430\u0446\u0435\u043b\u0435\u043d \u043d\u0430 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b.<\/p>\n<\/blockquote>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u0438 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u043a\u043e\u0432\u044b\u0440\u044f\u0432\u0448\u0438\u0441\u044c \u0441 \u043d\u0438\u043c, \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043c\u043d\u0435 \u043e\u043d \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442. \u042f \u043b\u044e\u0431\u043b\u044e \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u043b\u0435\u0433\u043a\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u0446\u0435\u043b\u0438 (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 pet-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0431\u044b\u0432\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b). \u042f \u043f\u0438\u0448\u0443 \u043d\u0430 Java \u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u044b Spring \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0438\u0445 \u0437\u0430\u0434\u0430\u0447. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0441\u043b\u0435 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 Keycloak \u0432\u044b\u0431\u043e\u0440 \u043f\u0430\u043b \u043d\u0430 Spring Security. \u041d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u044f \u0443\u0436\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b \u0441\u0435\u0440\u0432\u0435\u0440 SSO, \u043d\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Spring Boot 2 \u0438 Spring OAuth2, \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u043c\u043d\u0435 \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u043a\u0430\u043a \u043d\u0430 Spring Boot 3, \u0442\u0430\u043a \u0438 \u043d\u043e\u0432\u044b\u0439 Spring Authorization Server. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u0447\u0438\u0442\u0430\u0432 \u043f\u0430\u0440\u0443 \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430 \u0445\u0430\u0431\u0440\u0435 \u0438 \u0432\u043e\u043e\u0440\u0443\u0436\u0438\u0432\u0448\u0438\u0441\u044c \u0441\u0430\u043c\u044b\u043c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432 (\u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 Spring Authorization Server <code>1.0.2<\/code>, Spring Boot <code>3.0.6<\/code>), \u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043b \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e SSO \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u044f \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0447\u0442\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u0445 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 Spring Authorization Server, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438 \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e. \u0418\u0442\u0430\u043a, \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043e\u0442 \u0441\u043b\u043e\u0432 \u043a \u0434\u0435\u043b\u0443!<\/p>\n<h3>\u0426\u0435\u043b\u0438<\/h3>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0432\u043e\u0435\u0433\u043e SSO \u044f \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0441\u0435\u0431\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:<\/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<ol>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>Java 17<\/p>\n<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<\/ol>\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<ol>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<li>\n<p>\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<\/li>\n<\/ol>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 1: \u0421\u0442\u0440\u043e\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 Spring Authorization Server<\/h3>\n<p>\u041f\u0440\u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0432 Spring Authorization Server \u044f \u0431\u044b\u043b \u043f\u043e\u0440\u0430\u0436\u0435\u043d, \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043b\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0438 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u0432\u044b \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442\u0435\u0441\u044c \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438 \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043c\u0435\u043b\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438, \u0442\u0430\u043c \u0441 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c\u044e 80% \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Maven \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u043d\u0430\u0448\u0435\u0433\u043e sso server, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e j-sso. \u042f \u0441\u0440\u0430\u0437\u0443 \u0441\u043e\u0437\u0434\u0430\u043c \u043c\u043d\u043e\u0433\u043e\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Maven, \u0447\u0442\u043e\u0431\u044b \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u043d\u0430\u0448 demo-\u043f\u0440\u043e\u0435\u043a\u0442. \u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Maven \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 Spring Boot \u0438 Spring Authorization Server. \u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0432\u0435\u0440\u0441\u0438\u044f Spring Boot <code>3.0.6<\/code>, \u0430 Spring Authorization Server <code>1.0.2<\/code>. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e <code>pom.xml<\/code> \u0444\u0430\u0439\u043b\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 pom.xml<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt; &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\"&gt;     &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;      &lt;groupId&gt;ru.dlabs&lt;\/groupId&gt;     &lt;artifactId&gt;spring-authorization-server-example&lt;\/artifactId&gt;     &lt;packaging&gt;pom&lt;\/packaging&gt;     &lt;version&gt;0.0.1&lt;\/version&gt;     &lt;name&gt;spring-authorization-server-example&lt;\/name&gt;      &lt;properties&gt;         &lt;java.version&gt;17&lt;\/java.version&gt;         &lt;maven.compiler.target&gt;17&lt;\/maven.compiler.target&gt;         &lt;maven.compiler.source&gt;17&lt;\/maven.compiler.source&gt;         &lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;          &lt;security-oauth2-server.version&gt;1.0.2&lt;\/security-oauth2-server.version&gt;     &lt;\/properties&gt;      &lt;parent&gt;         &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;         &lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;         &lt;version&gt;3.0.5&lt;\/version&gt;         &lt;relativePath\/&gt;     &lt;\/parent&gt;      &lt;modules&gt;         &lt;module&gt;j-sso&lt;\/module&gt;     &lt;\/modules&gt;      &lt;dependencyManagement&gt;         &lt;dependencies&gt;             &lt;dependency&gt;                 &lt;groupId&gt;org.springframework.security&lt;\/groupId&gt;                 &lt;artifactId&gt;spring-security-oauth2-authorization-server                 &lt;\/artifactId&gt;                 &lt;version&gt;${security-oauth2-server.version}&lt;\/version&gt;             &lt;\/dependency&gt;         &lt;\/dependencies&gt;     &lt;\/dependencyManagement&gt; &lt;\/project&gt; <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e j-sso \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u044b Spring Boot:<\/p>\n<ul>\n<li>\n<p>spring-boot-starter-security<\/p>\n<\/li>\n<li>\n<p>spring-boot-starter-web<\/p>\n<\/li>\n<li>\n<p>spring-boot-starter<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0430\u043c Spring Authorization Server. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u043a\u0430\u043a\u0430\u044f-\u043d\u0438\u0431\u0443\u0434\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u042f \u043b\u044e\u0431\u043b\u044e \u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c log4j2. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u043b\u043e\u0433\u0433\u0435\u0440 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c log4j2. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u043c \u0438\u0437 <code>spring-boot-starter<\/code> <code>spring-boot-starter-logging<\/code> \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c <code>spring-boot-starter-log4j2<\/code>. \u041d\u0443 \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c <code>lombok<\/code>, \u043a\u0443\u0434\u0430 \u0436\u0435 \u043c\u044b \u0431\u0435\u0437 \u043d\u0435\u0433\u043e)) \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u043f\u043e\u043b\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f <code>pom.xml<\/code> \u0434\u043b\u044f \u043c\u043e\u0434\u0443\u043b\u044f j-sso.<\/p>\n<details class=\"spoiler\">\n<summary>pom.xml \u043c\u043e\u0434\u0443\u043b\u044f j-sso<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt; &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\"&gt;     &lt;parent&gt;         &lt;artifactId&gt;spring-authorization-server-example&lt;\/artifactId&gt;         &lt;groupId&gt;ru.dlabs&lt;\/groupId&gt;         &lt;version&gt;0.0.1&lt;\/version&gt;     &lt;\/parent&gt;     &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;      &lt;artifactId&gt;j-sso&lt;\/artifactId&gt;      &lt;properties&gt;         &lt;maven.compiler.source&gt;17&lt;\/maven.compiler.source&gt;         &lt;maven.compiler.target&gt;17&lt;\/maven.compiler.target&gt;     &lt;\/properties&gt;      &lt;dependencies&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter&lt;\/artifactId&gt;             &lt;exclusions&gt;                 &lt;exclusion&gt;                     &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;                     &lt;artifactId&gt;spring-boot-starter-logging&lt;\/artifactId&gt;                 &lt;\/exclusion&gt;             &lt;\/exclusions&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-log4j2&lt;\/artifactId&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.springframework.security&lt;\/groupId&gt;             &lt;artifactId&gt;spring-security-oauth2-authorization-server&lt;\/artifactId&gt;         &lt;\/dependency&gt;          &lt;dependency&gt;             &lt;groupId&gt;org.projectlombok&lt;\/groupId&gt;             &lt;artifactId&gt;lombok&lt;\/artifactId&gt;             &lt;version&gt;${lombok.version}&lt;\/version&gt;             &lt;scope&gt;provided&lt;\/scope&gt;         &lt;\/dependency&gt;     &lt;\/dependencies&gt;      &lt;build&gt;         &lt;finalName&gt;${project.artifactId}&lt;\/finalName&gt;         &lt;plugins&gt;             &lt;plugin&gt;                 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;                 &lt;artifactId&gt;spring-boot-maven-plugin&lt;\/artifactId&gt;                 &lt;configuration&gt;                     &lt;finalName&gt;${project.name}&lt;\/finalName&gt;                 &lt;\/configuration&gt;             &lt;\/plugin&gt;         &lt;\/plugins&gt;     &lt;\/build&gt; &lt;\/project&gt; <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 SSO \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 (\u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430) \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043d\u0430\u0448\u0435\u0433\u043e Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0432\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><code>SecurityConfig.java<\/code> &#8212; \u0432 \u043d\u0435\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0434\u0443\u043b\u044f j-sso.<\/p>\n<\/li>\n<li>\n<p><code>AuthorizationServerConfig.java<\/code> &#8212; \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">import static org.springframework.security.config.Customizer.withDefaults;  @EnableWebSecurity @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         http.authorizeHttpRequests(authorize -&gt;                 authorize.anyRequest().authenticated()         );         return http.formLogin(withDefaults()).build();     }      @Bean     public UserDetailsService users() {         UserDetails user = User.builder()                 .username(\"admin\")                 .password(\"{noop}password\")                 .roles(\"USER\")                 .build();         return new InMemoryUserDetailsManager(user);     } } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0430\u043c\u0443\u044e \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0438\u043d <code>SecurityFilterChain<\/code> \u0432 \u043d\u0435\u043c \u0443\u043a\u0430\u0436\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0437\u0430\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u043e\u0434 \u0441\u0435\u043a\u0443\u0440\u0438\u0442\u0438, \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u0445\u043e\u0434\u0430, \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u0443\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0443\u043a\u0430\u0437\u0430\u0432 <code>Customizer.withDefaults()<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 DSL \u043c\u0435\u0442\u043e\u0434\u0430 <code>formLogin(...)<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0438\u043d <code>UserDetailsService<\/code> \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0432 \u043d\u0435\u043c in memory \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041e\u043d \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h4>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Authorization Server.<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>AuthorizationServerConfig<\/code>. \u0412 \u043d\u0451\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0438\u043d <code>SecurityFilterChain<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u0443\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c\u044e <code>sp<\/code><\/p>\n<\/blockquote>\n<\/blockquote>\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-347894","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/347894","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=347894"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/347894\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=347894"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=347894"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=347894"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}