{"id":350373,"date":"2023-07-17T21:00:59","date_gmt":"2023-07-17T21:00:59","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=350373"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=350373","title":{"rendered":"<span>\u0421\u0442\u0440\u043e\u0438\u043c \u0441\u0432\u043e\u0439 SSO. \u0427\u0430\u0441\u0442\u044c 3: Redis, Swagger, Vue.js<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0430\u0442\u0435\u0439 \u044d\u0442\u043e\u0439 \u0441\u0435\u0440\u0438\u0438<\/h3>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/737548\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 1: \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<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/746698\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 2: \u0421\u0442\u0440\u043e\u0438\u043c \u0441\u0432\u043e\u0439 SSO. PostgreSQL \u0438 \u0440\u043e\u043b\u0435\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c<\/a><\/p>\n<\/li>\n<li>\n<p>\u0427\u0430\u0441\u0442\u044c 3: \u0421\u0442\u0440\u043e\u0438\u043c \u0441\u0432\u043e\u0439 SSO. \u0427\u0430\u0441\u0442\u044c 3: Redis, Swagger, Vue.js<\/p>\n<\/li>\n<\/ul>\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 SSO Server. \u0412 <a href=\"https:\/\/habr.com\/ru\/articles\/746698\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 Resource Server \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e SSO.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0421\u0423\u0411\u0414 PostgreSQL \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0440\u0430\u0441\u043a\u0430\u0442\u0430 \u0441\u0445\u0435\u043c\u044b \u0411\u0414.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446 \u0411\u0414 \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e \u043a\u043e\u0434\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0442\u0440\u0438 \u0442\u0438\u043f\u0430 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0435\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u0440\u043e\u043b\u0438 \u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438, \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 Spring Security.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0437 \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e (\u0441\u043c. \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 <a href=\"https:\/\/habr.com\/ru\/articles\/746698\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>) \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c Redis<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Swagger<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f <code>j-sso<\/code> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>Vue.js<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u044d\u0442\u0438 \u0442\u0440\u0438 \u043f\u0443\u043d\u043a\u0442\u0430. \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c!<\/p>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 3.1: \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c Redis<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0440\u0430\u0437\u0431\u043e\u0440\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0442\u043e\u043c, \u0437\u0430\u0447\u0435\u043c \u043c\u044b \u0432\u043e\u043e\u0431\u0449\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 Redis-\u0430 \u043a\u0430\u043a \u043a\u044d\u0448 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0442\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u044d\u0448\u0430. \u041d\u043e \u0437\u0430\u0447\u0435\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u044d\u0442\u043e\u0442 \u043a\u044d\u0448 \u0432 Redis-\u0435 \u0438 \u0447\u0442\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0442\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f? \u0414\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0441\u0442\u043e\u0438\u0442 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u0442\u0440\u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c &#8212; \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e (\u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438) \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043d\u0435\u0431\u043b\u0430\u0433\u043e\u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0445 \u043e\u0431\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430\u0445 (\u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u0445 \u0438\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0445 \u0441\u0431\u043e\u0435\u0432 \u043b\u0438\u0431\u043e \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).<\/p>\n<\/li>\n<li>\n<p>\u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c &#8212; \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0445 \u043f\u0440\u0438 \u0440\u043e\u0441\u0442\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u0440\u043e\u0431\u043b\u0435\u043c (\u043e\u0431\u044a\u0435\u043c\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u0438\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438).<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f &#8212; \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0443 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043b\u044e\u0434\u0435\u0439 (\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0438 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u044e\u0449\u0435\u043c\u0443 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u0443, \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c\u0441\u044f \u043a\u0430\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u0430\u043a \u0438 \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043a \u043d\u043e\u0432\u044b\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f).<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u043a \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u043c \u0441\u0431\u043e\u044f\u043c. \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0444\u0430\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0431\u043e\u0438 \u0432\u0438\u043d\u0447\u0435\u0441\u0442\u0435\u0440\u043e\u0432, \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u0444\u0435\u043a\u0442\u043e\u0432 \u041e\u0417\u0423, \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043f\u0438\u0442\u0430\u043d\u0438\u044f, \u0432\u044b\u0445\u043e\u0434 \u0438\u0437 \u0441\u0442\u0440\u043e\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043a\u0438, \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a\u0435\u043c-\u0442\u043e \u043d\u0435 \u0442\u043e\u0433\u043e \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u043a\u0430\u0431\u0435\u043b\u044f \u0438 \u0442.\u0434. \u0410 \u0432 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0432\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c, \u043a\u0430\u043a \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u0440\u0438 \u0432\u043e\u0437\u0440\u043e\u0441\u0448\u0435\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0435. \u0414\u043b\u044f \u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448 <code>j-sso<\/code> \u0432 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0432 \u0434\u0432\u0443\u0445, \u0430 \u0442\u043e \u0438 \u0431\u043e\u043b\u0435\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u0445 (\u0441\u043c. \u0441\u0445\u0435\u043c\u0443 \u043d\u0438\u0436\u0435).<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/post_images\/5ee\/4e0\/3a0\/5ee4e03a0edb5ddb04cbfedb3785ea7f.jpg\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b j-sso\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b j-sso\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/5ee\/4e0\/3a0\/5ee4e03a0edb5ddb04cbfedb3785ea7f.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b j-sso<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u044d\u0442\u043e \u043f\u043e\u043d\u044f\u043b\u0438, \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e <code>j-sso<\/code>, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e Spring Security \u0438 \u0438\u0436\u0438 \u0441 \u043d\u0438\u043c\u0438, \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f \u0445\u0440\u0430\u043d\u0438\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438 \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 <code>j-sso<\/code>, \u0442\u043e \u043d\u0430 \u043a\u0430\u043a\u043e\u043c \u0438\u0437 \u043d\u0438\u0445 \u0431\u0443\u0434\u0443 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438? \u0418 \u0432\u043e \u0432\u0442\u043e\u0440\u044b\u0445, \u043d\u0430 \u043a\u0430\u043a\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043c\u044b \u043f\u043e\u043f\u0430\u0434\u0435\u043c \u043f\u043e\u0441\u043b\u0435 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438?<\/p>\n<p>\u0412\u0441\u0435 \u043f\u0430\u0440\u0438\u043b\u044c\u043d\u043e, \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 &#171;\u0440\u0430\u0437\u043c\u0430\u0437\u0430\u043d\u044b&#187; \u043f\u043e \u0432\u0441\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c, \u0430 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430 \u043a\u0430\u043a\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u043e\u043f\u0430\u0434\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043a\u0430\u043a\u043e\u0435-\u043d\u0438\u0431\u0443\u0434\u044c In Memory Data Grid \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 Redis. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 IMDG \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u044f \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e, \u0430 Spring \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435\u043e\u0431\u044a\u0435\u043c\u043b\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Redis, \u0442\u043e \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0435\u0433\u043e.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0436\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u044d\u0442\u043e\u0442 Redis \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043c Spring Security \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0430\u0448 <code>docker-compose.yml<\/code> \u0444\u0430\u0439\u043b \u0441\u0435\u0440\u0432\u0438\u0441 <code>j-redis<\/code>, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0441 \u0447\u0435\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p><code><strong>docker-compose.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\"> version: '3.3' services:   \/\/ .....    j-redis:     image: redis:7.2-rc2     restart: always     command: redis-server --save 20 1 --loglevel warning --requirepass qwerty12345678     ports:       - '6379:6379'     networks:       - j-network    \/\/ ..... <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.spring.io\/spring-data\/data-redis\/docs\/current\/reference\/html\/\" rel=\"noopener noreferrer nofollow\"><code>spring-boot-starter-data-redis<\/code><\/a> &#8212; \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f <code>j-sso<\/code> \u043a Redis.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.spring.io\/spring-session\/reference\/guides\/boot-redis.html\" rel=\"noopener noreferrer nofollow\"><code>spring-session-data-redis<\/code><\/a> &#8212; \u043d\u0443\u0436\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 Spring Session \u0432 Redis<\/p>\n<\/li>\n<\/ul>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ .....     &lt;dependencies>         &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-starter-data-redis&lt;\/artifactId>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.springframework.session&lt;\/groupId>             &lt;artifactId>spring-session-data-redis&lt;\/artifactId>         &lt;\/dependency>     &lt;\/dependencies>     \/\/ .....  &lt;\/project> <\/code><\/pre>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432 \u043d\u0430\u0448 <code>application.yml<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c:<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">spring:   application:     name: j-sso   session:     timeout: 1800                 # \u0412\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u0441\u0435\u0441\u0441\u0438\u0438 (\u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445)     redis:       flush-mode: on_save         # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u043e\u0433\u0434\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0430\u043d\u0441\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 (immediate \u0438\u043b\u0438 on_save)       namespace: j-sso:session    # \u041f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438\u043c\u0435\u043d \u0434\u043b\u044f \u043a\u043b\u044e\u0447\u0435\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0439.       save-mode: on_set_attribute # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0432 \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 (on_set_attribute, on_get_attribute, always)   data:     redis:                          # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a Redis       client-type: lettuce        # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0438\u043f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Redis (jedis \u0438\u043b\u0438 lettuce)       database: 0                 # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u043e\u043c\u0435\u0440 \u0411\u0414 Redis       host: localhost             # \u0425\u043e\u0441\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f       port: 6379                  # \u041f\u043e\u0440\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f       password: qwerty12345678    # \u041f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f       lettuce:                      # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043f\u0443\u043b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 lettuce         pool:           max-active: 16          # \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432 \u043f\u0443\u043b\u0435           max-idle: 8             # \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \"idle\" \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432 \u043f\u0443\u043b\u0435 <\/code><\/pre>\n<p>\u0412\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0435, \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b Spring Session \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/3.0.7\/reference\/htmlsingle\/#application-properties.web.spring.session.redis.cleanup-cron\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b Spring Data Redis \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/3.0.7\/reference\/htmlsingle\/#application-properties.data.spring.data.redis.client-name\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0441\u0443\u0434\u0438\u0442\u044c \u043f\u043e\u0447\u0435\u043c\u0443 <code>lettuce<\/code>, \u0430 \u043d\u0435 <code>jedis<\/code>. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (\u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 <code>spring-session-data-redis<\/code>). \u0410 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0435\u0442 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0432\u0435\u0441\u043e\u043c\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>lettuce<\/code>. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 <code>jedis<\/code> \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0433 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d, \u043a\u0430\u043a \u0438 <code>lettuce<\/code>.<\/p>\n<ul>\n<li>\n<p>Lettuce \u2014 \u044d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 Java-\u043a\u043b\u0438\u0435\u043d\u0442 Redis. \u041e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043a\u0430\u043a \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0443\u044e, \u0442\u0430\u043a \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c. \u0415\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p>Jedis \u2014 \u044d\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 Redis, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041e\u043d \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043d\u043e \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443, \u043a\u043b\u0438\u0435\u043d\u0442 <code>lettuce<\/code>, \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 \u0437\u0430 \u0441\u0447\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u041d\u043e \u043e\u043d \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0432 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u0441 Redis.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 (\u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>postgresql<\/code> \u0438 <code>redis<\/code>). \u0414\u0430\u043b\u0435\u0435, \u043f\u0440\u043e\u0439\u0434\u0435\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043b\u044e\u0431\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0438 \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 Redis.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/547\/f09\/df5\/547f09df50056937f795741f23ce6b38.png\" alt=\"\u0414\u0430\u043d\u043d\u044b\u0435 \u0432 Redis \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\" title=\"\u0414\u0430\u043d\u043d\u044b\u0435 \u0432 Redis \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/547\/f09\/df5\/547f09df50056937f795741f23ce6b38.png\"\/><\/p>\n<div><figcaption>\u0414\u0430\u043d\u043d\u044b\u0435 \u0432 Redis \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043f\u043e\u0434 \u043a\u043b\u044e\u0447\u043e\u043c \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0448\u0435\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 (\u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0443\u043a\u0438 <code>JSESSIONID<\/code>) \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0440\u044f\u0434 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u0440\u0435\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c Spring Security Context. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0448\u0438\u0445 \u0441\u0435\u0441\u0441\u0438\u0439 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 Redis. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 <code>j-sso<\/code>, \u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0438 \u0432\u0441\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438. \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e \u043f\u0440\u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0418\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u0447\u0430\u0441\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u044e\u0442 \u0441\u0432\u043e\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0438\u0449\u0443\u0442 \u0447\u0430\u0441\u0430\u043c\u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043a\u043e\u0434\u0435, \u0430 \u043d\u0430\u0434\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c Redis.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>j-sso<\/code> \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u0445 \u0438 \u043d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u0442\u044c\u0441\u044f \u043e \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430 \u0432\u0441\u0435\u0445 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b. \u041f\u043b\u044e\u0441\u043e\u043c \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u0432\u044b\u0448\u0435\u0441\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443, \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u0441\u0441\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 Redis \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e.<\/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.1\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 3.2: \u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e Swagger<\/h3>\n<blockquote>\n<p>Swagger \u2014 \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 API \u043e\u0442 SmartBear Software \u0438 \u0431\u044b\u0432\u0448\u0430\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f OpenAPI.<\/p>\n<\/blockquote>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c:<\/p>\n<ol>\n<li>\n<p>OpenAPI 3 &#8212; \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0438 \u0438\u0445 endpoint-\u044b. <a href=\"https:\/\/spec.openapis.org\/oas\/latest.html\" rel=\"noopener noreferrer nofollow\">OpenAPI Specification<\/a><\/p>\n<\/li>\n<li>\n<p>Swagger UI &#8212; \u044d\u0442\u043e \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 OpenAPI. \u041e\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 endpoint-\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043d\u0430\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043b\u0435\u0433\u043a\u043e \u0438 \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u0442\u0435\u043b\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 API, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0435\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u041f\u041e.<\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f Swagger \u0432 Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0432\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438: Springfox \u0438 Springdoc. Springfox \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0435\u0440\u0435\u043c <a href=\"https:\/\/springdoc.org\/\" rel=\"noopener noreferrer nofollow\">Springdoc<\/a>.<\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043e\u0447\u0435\u043d\u044c \u0433\u0440\u0430\u043c\u043e\u0442\u043d\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430, \u043e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0441\u0432\u043e\u044e \u0447\u0430\u0441\u0442\u044c. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438\u0437 \u0438\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e <code>2.x.x<\/code>. \u0412\u0435\u0440\u0441\u0438\u044f <code>1.7.\u0445<\/code> \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e Spring Boot 3.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/881\/323\/8f4\/8813238f4da1ddcc296115ec5361d997.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 springdoc\" title=\"\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 springdoc\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/881\/323\/8f4\/8813238f4da1ddcc296115ec5361d997.png\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 springdoc<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b, springdoc \u0438\u043c\u0435\u0435\u0442 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 Spring MVC, \u0442\u0430\u043a \u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0434\u043b\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 WebFlux. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0442\u0435 \u0447\u0442\u043e \u0441\u043f\u0440\u0430\u0432\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c WebFlux. \u0422\u0430\u043a\u0436\u0435, springdoc \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u043d\u0430 \u0442\u0435, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u0448\u0438\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432, \u043f\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OpenAPI. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u044d\u0442\u0438\u043c \u0435\u0449\u0451 \u0438 Swagger UI, \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432\u0441\u0435 \u0432 <code>j-sso<\/code>, \u0442\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432 \u043d\u0430\u0448 <code>pom.xml<\/code>:<\/p>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ ...      &lt;dependency>         &lt;groupId>org.springdoc&lt;\/groupId>         &lt;artifactId>springdoc-openapi-starter-webmvc-ui&lt;\/artifactId>         &lt;version>2.1.0&lt;\/version>     &lt;\/dependency>      \/\/ ... &lt;\/project> <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0438\u043d \u043a\u043b\u0430\u0441\u0441\u0430 <code>OpenAPI<\/code> \u0432 \u043d\u0430\u0448\u0435\u043c <code>RootConfig<\/code>. \u0412 \u043d\u0435\u043c \u043c\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0438\u043c\u044f, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u0432\u0435\u0440\u0441\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u042d\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u0435\u0434\u0435\u043d\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Swagger.<\/p>\n<p><code><strong>RootAppConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @Configuration @RequiredArgsConstructor @EnableJpaRepositories(basePackages = \"ru.dlabs.sas.example.jsso.dao.repository\") public class RootAppConfig {      \/\/ ....      @Bean     public OpenAPI openAPI() {         return new OpenAPI()                 .info(new Info()                         .title(\"\u041d\u0430\u0448 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u044b\u0439 SSO\")                         .description(\"\u041d\u0435\u043a\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e SSO\")                         .version(\"0.0.1\")                 );     } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0448 <code>j-sso<\/code> \u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u0432\u0430 endpoint-\u0430.<\/p>\n<ul>\n<li>\n<p><code>http:\/\/localhost:7777\/swagger-ui\/index.html<\/code> &#8212; \u043f\u043e \u043d\u0435\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d Swagger UI<\/p>\n<\/li>\n<li>\n<p><code>http:\/\/localhost:7777\/v3\/api-docs<\/code> &#8212; \u043f\u043e \u043d\u0435\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f OpenAPI \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 json \u0444\u043e\u0440\u043c\u0430\u0442\u0435<\/p>\n<\/li>\n<\/ul>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/274\/14e\/ceb\/27414eceb0c7eebd6bcc755ff6c1caf3.png\" alt=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-sso \u0432 Swagger UI\" title=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-sso \u0432 Swagger UI\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/274\/14e\/ceb\/27414eceb0c7eebd6bcc755ff6c1caf3.png\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-sso \u0432 Swagger UI<\/figcaption><\/div>\n<\/figure>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u043d\u0430\u0448 SSO \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0440\u043e\u0439\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e. \u042d\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0443\u0434\u043e\u0431\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a Swagger UI \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e SSO \u043d\u0435 \u0438\u043c\u0435\u0435\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0435\u0433\u043e endpoint-\u044b \u0438\u0437-\u043f\u043e\u0434 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 Security. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u0438\u0437\u043c\u0435\u043d\u0438\u043c <code>SecurityConfig<\/code> \u0438 <code>AuthorizationServerConfig<\/code> \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 @EnableMethodSecurity @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {      \/\/ ...      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {          \/\/ ...          http.authorizeHttpRequests(authorize ->                 authorize                         \/\/ endpoint-\u044b swagger \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0438\u0437 \u043f\u043e\u0434 security                         .requestMatchers(                                 \"\/v3\/api-docs\",                                 \"\/swagger-ui\/**\",                                 \"\/v3\/api-docs\/swagger-config\"                         ).permitAll()                         .anyRequest().authenticated()         );         return http.formLogin(withDefaults()).build();     } } <\/code><\/pre>\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 {          \/\/ .....          RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();         http.securityMatcher(endpointsMatcher)                 .authorizeHttpRequests(authorize ->                         authorize                                 \/\/ endpoint-\u044b swagger \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0438\u0437 \u043f\u043e\u0434 security                                 .requestMatchers(                                         \"\/v3\/api-docs\",                                         \"\/swagger-ui\/**\",                                         \"\/v3\/api-docs\/swagger-config\"                                 ).permitAll()                                 .anyRequest().authenticated()                 )         \/*...*\/;         return http.build();     } } <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 Swagger UI \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430 \u043d\u0438\u0445 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0432 <code>application.yml<\/code>. \u041c\u044b \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \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. \u0412\u0435\u0441\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/springdoc.org\/properties.html\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">\/\/ ...  springdoc:   swagger-ui:     enabled: true     use-root-path: true     path: \/swagger-ui     doc-expansion: none     config-url: \/v3\/api-docs\/swagger-config     disable-swagger-default-url: true     operationsSorter: method     tagsSorter: alpha     url: \/v3\/api-docs     try-it-out-enabled: true   api-docs:     enabled: true     path: \/v3\/api-docs    \/\/ ... <\/code><\/pre>\n<ul>\n<li>\n<p><code>swagger-ui.use-root-path<\/code> &#8212; \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u043c true, \u0447\u0442\u043e\u0431\u044b swagger-ui \u0431\u044b\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0438\u0437 \u043a\u043e\u0440\u043d\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.path<\/code> &#8212; \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0443\u0442\u044c \u0434\u043e HTML \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b swagger-ui<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.doc-expansion<\/code> &#8212; \u044d\u0442\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u0441\u043f\u0438\u0441\u043a\u0430\u0445. \u041c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 \u0438\u043b\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.config-url<\/code> &#8212; \u043c\u043e\u0436\u043d\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c URL \u0434\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 HTML \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b swagger-ui. \u041c\u044b \u0435\u0433\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.disable-swagger-default-url<\/code> &#8212; \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e swagger-ui \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 Pet Store (\u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u0435\u0440\u0432\u0438\u0441\u0430). \u041d\u0430\u043c \u044d\u0442\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u043c<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.operationsSorter<\/code> &#8212; \u0432\u043a\u043b\u044e\u0447\u0438\u043c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u043f\u043e HTTP \u043c\u0435\u0442\u043e\u0434\u0430\u043c<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.tagsSorter<\/code> &#8212; \u0432\u043a\u043b\u044e\u0447\u0438\u043c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u043f\u043e \u0430\u043b\u0444\u0430\u0432\u0438\u0442\u0443 \u0432 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.url<\/code> &#8212; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c URL \u0434\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OpenAPI \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/p>\n<\/li>\n<li>\n<p><code>swagger-ui.try-it-out-enabled<\/code> &#8212; \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c\/\u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0437 swagger-ui<\/p>\n<\/li>\n<li>\n<p><code>api-docs.path<\/code> &#8212; \u043c\u043e\u0436\u043d\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u0434\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OpenAPI \u043d\u0430\u0448\u0435\u0433\u043e <code>j-sso<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 Swagger \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443. \u041d\u043e \u044d\u0442\u043e \u0435\u0449\u0435 \u043d\u0435 \u0432\u0441\u0435. \u041d\u0430\u043c \u043d\u0430\u0434\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0439\u0442\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441 \u0444\u043e\u0440\u043c\u044b swagger-ui. \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 (<code>j-sso<\/code> \u0438 <code>j-service<\/code>), \u0430 \u0434\u0430\u043b\u044c\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0441\u0431\u043e\u0440\u043a\u0443 Swagger UI. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Swagger UI \u0438 \u0432 \u043f\u043e\u043b\u0435 Explorer \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u043d\u0430\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u041d\u043e \u0432\u0441\u0435 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a-\u0442\u043e \u043d\u0435 \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<p>\u041e\u0431\u044b\u0447\u043d\u043e, \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439, Swagger UI \u0441\u0442\u0430\u0432\u044f\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0432\u0438\u0441, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 Gateway &#8212; \u044d\u0442\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/github.com\/Netflix\/zuul\" rel=\"noopener noreferrer nofollow\">Zuul<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/spring.io\/projects\/spring-cloud-gateway\" rel=\"noopener noreferrer nofollow\">Spring Cloud Gateway<\/a>. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c Swagger UI \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u043e\u043b\u044f &#171;Explorer&#187;, \u0432\u044b\u0431\u0438\u0440\u0430\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0443\u0436\u043d\u0430\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b, \u0447\u0442\u043e\u0431\u044b \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u0447\u0442\u043e-\u0442\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e\u0435, \u043d\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 gateway, \u0443 \u043d\u0430\u0441 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e pet-\u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Swagger UI. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u044c <code>j-swagger-ui<\/code> \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0432 \u043d\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0435 Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u0430\u043b\u0435\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c <code>springdoc-openapi-starter-webmvc-ui<\/code>. \u0414\u0430\u043b\u0435\u0435, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043c\u043e\u0434\u0443\u043b\u044e <code>j-sso<\/code>, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c swagger-ui. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u044b \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OpenAPI \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <code>springdoc.api-docs.enabled = false<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430. \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 \u0444\u0430\u0439\u043b <code>application.yml<\/code> \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430:<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">server:   port: 7778  logging:   level:     root: INFO     org.springframework.security.web.FilterChainProxy: ERROR     logging.level.org.hibernate.SQL: INFO     com.zaxxer.hikari: ERROR     org.postgresql: ERROR  spring:   application:     name: j-swagger-ui  springdoc:   swagger-ui:     enabled: true     use-root-path: true     doc-expansion: none     disable-swagger-default-url: true     operationsSorter: method     tagsSorter: alpha     try-it-out-enabled: true     urls:       - name: SSO Server         url: http:\/\/localhost:7777\/v3\/api-docs   api-docs:     enabled: true <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0432 springdoc \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <code>springdoc.swagger-ui.urls[0].*<\/code>. \u0421 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/ecc\/7c9\/a9e\/ecc7c9a9eba303f73d01b91f0a6b472d.png\" alt=\"Swagger UI \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 j-swagger-ui\" title=\"Swagger UI \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 j-swagger-ui\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/ecc\/7c9\/a9e\/ecc7c9a9eba303f73d01b91f0a6b472d.png\"\/><\/p>\n<div><figcaption>Swagger UI \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 j-swagger-ui<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0441\u0432\u0435\u0440\u0445\u0443 \u0435\u0441\u0442\u044c \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>urls<\/code>. \u0410 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0437\u0430\u043f\u0440\u0435\u0442\u0430 \u043a\u0440\u043e\u0441\u0441-\u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<blockquote>\n<p>Cross-Origin Resource Sharing (CORS) \u2014 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0434\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0435 (\u0434\u043e\u043c\u0435\u043d\u0435), \u043e\u0442\u043b\u0438\u0447\u043d\u043e\u043c \u043e\u0442 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0441\u0430\u0439\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. \u0413\u043e\u0432\u043e\u0440\u044f\u0442, \u0447\u0442\u043e \u0430\u0433\u0435\u043d\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 (cross-origin HTTP request), \u0435\u0441\u043b\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0434\u043e\u043c\u0435\u043d\u043e\u043c, \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u043c \u0438\u043b\u0438 \u043f\u043e\u0440\u0442\u043e\u043c.<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 \u0434\u043e\u043c\u0435\u043d\u0430 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043d\u0430\u0448 <code>j-swagger-ui<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 <code>j-sso<\/code> \u0438 \u043d\u0430\u0439\u0434\u0435\u043c \u0431\u0438\u043d <code>corsFilter<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c CORS. \u041d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>http:\/\/localhost:7778<\/code> \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>AllowOrigins<\/code> \u0438 \u0432\u0441\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u0443\u0436\u0435 \u0432\u0442\u043e\u0440\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e CORS, \u0442\u043e \u0434\u0443\u043c\u0430\u044e \u043f\u043e\u0440\u0430 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 cors \u0432 <code>application.yml<\/code>. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>AppProperties<\/code> \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u0434\u043b\u044f CORS \u0441\u0435\u0439\u0447\u0430\u0441:<\/p>\n<p><code><strong>AppProperties.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Configuration public class AppProperties {      @Getter     @Setter     @Configuration     @ConfigurationProperties(prefix = \"spring.mvc.cors\")     public static class CorsProperties {          private List&lt;CorsConfig> configs;          public static record CorsConfig(                 String pattern,                 String allowedOrigins,                 String allowedOriginPatterns,                 String allowedHeaders,                 String exposedHeaders,                 String allowedMethods,                 Boolean allowCredentials,                 Long maxAge         ) {          }     } } <\/code><\/pre>\n<p>\u041c\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c CORS \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443. \u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 <code>application.yml<\/code>. \u041f\u0440\u0438 \u0447\u0435\u043c, \u0434\u043b\u044f <code>http:\/\/localhost:8080<\/code> \u0438 <code>http:\/\/localhost:7778<\/code> \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">   \/\/ .....   spring:     application:       name: j-sso     mvc:       cors:         configs:           - pattern: \/v3\/api-docs             allowed-origins: \"http:\/\/localhost:7778\"             allowed-header: \"*\"             exposed-headers: \"*\"             allowed-methods: \"*\"             allow-credentials: true           - pattern: \/**             allowed-origins: \"http:\/\/127.0.0.1:8080,http:\/\/localhost:8080\"             allowed-header: \"*\"             exposed-headers: \"*\"             allowed-methods: \"*\"             allow-credentials: true      \/\/ ..... <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0431\u0438\u043d <code>corsFilter<\/code>, \u0442\u0430\u043a \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/p>\n<p><code><strong>RootAppConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @Configuration @RequiredArgsConstructor @EnableJpaRepositories(basePackages = \"ru.dlabs.sas.example.jsso.dao.repository\") public class RootAppConfig {      \/\/ .....      @Bean     public FilterRegistrationBean&lt;CorsFilter> corsFilter() {         log.debug(\"CREATE CORS FILTER\");         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();         corsProperties.getConfigs().forEach(configProps -> {             CorsConfiguration config = new CorsConfiguration();             config.setAllowCredentials(configProps.allowCredentials());             config.addAllowedOrigin(configProps.allowedOrigins());             config.addAllowedOriginPattern(configProps.allowedOriginPatterns());             config.addAllowedHeader(configProps.allowedHeaders());             config.addExposedHeader(configProps.exposedHeaders());             config.addAllowedMethod(configProps.allowedMethods());             source.registerCorsConfiguration(configProps.pattern(), config);         });         FilterRegistrationBean&lt;CorsFilter> bean = new FilterRegistrationBean&lt;>(new CorsFilter(source));         bean.setOrder(Ordered.HIGHEST_PRECEDENCE);         return bean;     }      \/\/ ....  } <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e \u0441 <code>j-swagger-ui<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/f0a\/a42\/74a\/f0aa4274a24ff660472df882355e1e42.png\" alt=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-sso \u0432 Swagger UI\" title=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-sso \u0432 Swagger UI\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/f0a\/a42\/74a\/f0aa4274a24ff660472df882355e1e42.png\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-sso \u0432 Swagger UI<\/figcaption><\/div>\n<\/figure>\n<p>\u0418\u0442\u0430\u043a, \u0432\u0441\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u043a\u0430\u043a \u043c\u044b \u0438 \u0445\u043e\u0442\u0435\u043b\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c <code>j-service<\/code>.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c <code>springdoc-openapi-starter-webmvc-api<\/code> \u0432 \u0435\u0433\u043e <code>pom.xml<\/code>. \u0414\u0430, \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d swagger-ui \u0432 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 <code>j-sso<\/code> \u0438 <code>j-service<\/code>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0443 \u043d\u0438\u0445 \u043e\u0431\u043e\u0438\u0445 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c <code>springdoc-openapi-starter-webmvc-api<\/code> \u0432\u043c\u0435\u0441\u0442\u043e <code>springdoc-openapi-starter-webmvc-ui<\/code>.<\/p>\n<p><code><strong>j-service\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ ....     &lt;dependencies>         \/\/ ....         &lt;dependency>             &lt;groupId>org.springdoc&lt;\/groupId>             &lt;artifactId>springdoc-openapi-starter-webmvc-api&lt;\/artifactId>         &lt;\/dependency>     &lt;\/dependencies>      \/\/ ....  &lt;\/project> <\/code><\/pre>\n<p>\u0427\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u0440\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>config<\/code> \u0432 <code>j-service<\/code>. \u0412\u0441\u0435 \u0447\u0442\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a <code>security<\/code> \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432 \u043f\u043e\u0434\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0441 \u043e\u0434\u043d\u043e\u0438\u043c\u0435\u043d\u043d\u044b\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u0430\u043a \u0438 \u0432 <code>j-sso<\/code> \u043a\u043b\u0430\u0441\u0441 <code>RootAppConfig<\/code>. \u0414\u0430\u043b\u0435\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c CORS \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0431\u0438\u043d <code>OpenAPI openAPI()<\/code> \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0435. \u0412\u0441\u0435 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043c\u044b \u0443\u0436\u0435 \u0434\u0435\u043b\u0430\u043b\u0438 \u0432 <code>j-sso<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-3.2\/j-service\/src\/main\/java\/ru\/dlabs\/sas\/example\/jservice\/config\/RootAppConfig.java\" rel=\"noopener noreferrer nofollow\"><code>RootAppConfig<\/code><\/a> \u0438 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/blob\/chapter-3.2\/j-service\/src\/main\/resources\/application.yml\" rel=\"noopener noreferrer nofollow\"><code>application.yml<\/code><\/a> \u0432 Github \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438.<\/p>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 <code>j-swagger-ui<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>urls<\/code>:<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">\/\/ .... springdoc:   swagger-ui:     enabled: true     use-root-path: true     doc-expansion: none     disable-swagger-default-url: true     operationsSorter: method     tagsSorter: alpha     try-it-out-enabled: true     urls:       - name: SSO Server         url: http:\/\/localhost:7777\/v3\/api-docs       - name: J Service         url: http:\/\/localhost:9001\/v3\/api-docs    \/\/ .... <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0432\u0441\u0435 \u0442\u0440\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u0444\u043e\u0440\u043c\u0443 Swagger UI \u0438 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0442\u0435\u043f\u0435\u0440\u044c \u0438\u0445 \u0434\u0432\u0430 \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/e57\/a4b\/025\/e57a4b025deafe1997cffbcd46e3d7a2.png\" alt=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-service \u0432 Swagger UI\" title=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-service \u0432 Swagger UI\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e57\/a4b\/025\/e57a4b025deafe1997cffbcd46e3d7a2.png\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 j-service \u0432 Swagger UI<\/figcaption><\/div>\n<\/figure>\n<p>\u0418\u0442\u0430\u043a, \u0432\u0440\u043e\u0434\u0435 \u0431\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e. \u041d\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0443\u0434\u043e\u0431\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438\u0437 maven, \u0430 \u043d\u0435 \u0440\u0443\u043a\u0430\u043c\u0438 \u043c\u0435\u043d\u044f\u0442\u044c \u044d\u0442\u043e \u0432 java \u043a\u043e\u0434\u0435. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0432 <code>pom.xml<\/code> \u0435\u0441\u0442\u044c \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440\u044b <code>&lt;name><\/code> \u0438 <code>&lt;description><\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u0438 \u0435\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f. \u0411\u044b\u043b\u043e \u0431\u044b \u0443\u0434\u043e\u0431\u043d\u043e \u0432\u0441\u0435 \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0438\u043d\u0430 <code>openAPI<\/code>.<\/p>\n<p>\u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 Spring Boot \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 <code>META-INF\/build-info.properties<\/code> \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u0431\u043e\u0440\u043a\u0435 \u0438 \u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0431\u0438\u043d\u0430 <code>BuildProperties buildProperties<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b <code>build-info.properties<\/code> \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0442\u0443\u0434\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 <code>pom.xml<\/code>. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0440\u0435\u0448\u0438\u0442\u044c, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c. \u0418 \u0442\u0443\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 Spring Boot \u0443\u0436\u0435 \u0437\u0430 \u043d\u0430\u0441 \u0432\u0441\u0435 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b\u0438. \u0412 maven-\u043f\u043b\u0430\u0433\u0438\u043d\u0435 <code>spring-boot-maven-plugin<\/code>, \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 <code>build-info<\/code>, \u043e\u043d\u0430 \u043a\u0430\u043a \u0440\u0430\u0437 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">     &lt;parent>         &lt;artifactId>spring-authorization-server-example&lt;\/artifactId>         &lt;groupId>ru.dlabs&lt;\/groupId>         &lt;version>0.0.1&lt;\/version>     &lt;\/parent>     &lt;modelVersion>4.0.0&lt;\/modelVersion>      &lt;artifactId>j-sso&lt;\/artifactId>     &lt;name>SSO Server&lt;\/name>     &lt;description>\u0415\u0434\u0438\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \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\u0435\u0439&lt;\/description>      &lt;properties>         &lt;maven.compiler.source>17&lt;\/maven.compiler.source>         &lt;maven.compiler.target>17&lt;\/maven.compiler.target>         &lt;build-date>${maven.build.timestamp}&lt;\/build-date>         &lt;maven.build.timestamp.format>yyyy-MM-dd HH:mm&lt;\/maven.build.timestamp.format>     &lt;\/properties>      \/\/ ....      &lt;build>         &lt;finalName>${project.artifactId}&lt;\/finalName>         &lt;plugins>             &lt;plugin>                 &lt;groupId>org.springframework.boot&lt;\/groupId>                 &lt;artifactId>spring-boot-maven-plugin&lt;\/artifactId>                 &lt;configuration>                     &lt;finalName>${project.name}&lt;\/finalName>                 &lt;\/configuration>                 &lt;executions>                     &lt;!-- \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f build-info.properties \u0444\u0430\u0439\u043b\u0430-->                     &lt;execution>                         &lt;goals>                             &lt;goal>build-info&lt;\/goal>                         &lt;\/goals>                         &lt;configuration>                             &lt;!-- \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b: \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u0432\u0440\u0435\u043c\u044f \u0441\u0431\u043e\u0440\u043a\u0438-->                             &lt;additionalProperties>                                 &lt;description>${project.description}&lt;\/description>                                 &lt;build-date>${build-date}&lt;\/build-date>                             &lt;\/additionalProperties>                         &lt;\/configuration>                     &lt;\/execution>                 &lt;\/executions>             &lt;\/plugin>              \/\/ ....         &lt;\/plugins>     &lt;\/build>  &lt;\/project> <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438, \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>j-sso\/target\/classes\/META-INF<\/code> \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0444\u0430\u0439\u043b <code>build-info.properties<\/code> \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c:<\/p>\n<p><code><strong>build-info.properties<\/strong><\/code><\/p>\n<pre><code>build.artifact=j-sso build.build-date=2023-07-01 16\\:57 build.description=\u0415\u0434\u0438\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \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\u0435\u0439 build.group=ru.dlabs build.name=SSO Server build.time=2023-07-01T16\\:57\\:57.756Z build.version=0.0.1 <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0431\u0438\u043d <code>buildProperties<\/code> \u0432 \u043d\u0430\u0448 <code>RootAppConfig<\/code> \u0438 \u0447\u0443\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0431\u0438\u043d <code>openAPI<\/code>.<\/p>\n<p><code><strong>RootAppConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @Configuration @RequiredArgsConstructor @EnableJpaRepositories(basePackages = \"ru.dlabs.sas.example.jsso.dao.repository\") public class RootAppConfig {      private final AppProperties.CorsProperties corsProperties;     private final BuildProperties buildProperties;      \/\/ .....      @Bean     public OpenAPI openAPI() {         String buildDate = buildProperties.get(\"build-date\");         String buildInfo = \"&lt;h4>Build date: \" + buildDate + \"&lt;\/h4>\"                 + \"&lt;br>\" + buildProperties.get(\"description\");         return new OpenAPI()                 .info(new Info()                         .title(buildProperties.getName())                         .description(buildInfo)                         .version(buildProperties.getVersion())                 );     } } <\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0438 \u0432 <code>j-service<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e, \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0435\u0440\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0432\u0441\u0435 \u0442\u0440\u0438 \u043d\u0430\u0448\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430\u0445 \u043d\u0438\u0436\u0435.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/da8\/d84\/e65\/da8d84e65902a4e991352be341e5c47e.png\" alt=\"\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 j-service\" title=\"\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 j-service\" width=\"600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/da8\/d84\/e65\/da8d84e65902a4e991352be341e5c47e.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 j-service<\/figcaption><\/div>\n<\/figure>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/709\/812\/681\/7098126819bff9e2c9e1d313334e7644.png\" alt=\"\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 j-sso\" title=\"\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 j-sso\" width=\"600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/709\/812\/681\/7098126819bff9e2c9e1d313334e7644.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 j-sso<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0440\u043e\u0434\u0435 \u0431\u044b, \u0432\u0441\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e, \u043d\u043e \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043d\u0435 \u043c\u0430\u043b\u043e\u0432\u0430\u0436\u043d\u0430\u044f \u0434\u0435\u0442\u0430\u043b\u044c. \u041d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Swagger UI \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 endpoint-\u043e\u0432. \u041e\u043d\u0430 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0435\u0441\u0442\u044c, \u043d\u043e \u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a <code>Authorization<\/code> \u0441 \u0442\u043e\u043a\u0435\u043d\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0431\u0438\u043d \u0441 \u0442\u0438\u043f\u043e\u043c <code>OperationCustomizer<\/code> \u0438 \u0432 \u043d\u0435\u043c \u0443\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043a \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 endpoint-\u0430. \u0422\u0430\u043a\u0436\u0435, \u0441\u0440\u0430\u0437\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\/\u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430, \u043f\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>springdoc.auth.auth-header-enabled<\/code> \u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@ConditionalOnProperty<\/code>.<\/p>\n<p><code><strong>RootAppConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @Configuration @RequiredArgsConstructor public class RootAppConfig {      \/\/ ....      @Bean     @ConditionalOnProperty(value = \"springdoc.auth.auth-header-enabled\", havingValue = \"true\")     public OperationCustomizer customGlobalHeaders() {         return (Operation operation, HandlerMethod handlerMethod) -> {             Parameter authorizationHeader = new Parameter()                     .in(ParameterIn.HEADER.toString())                     .schema(new StringSchema())                     .name(\"Authorization\")                     .description(\"Authorization Header (Bearer or Basic)\")                     .required(false);             operation.addParametersItem(authorizationHeader);             return operation;         };     } } <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c3d\/a12\/bdf\/c3da12bdfe14730cec2af47b7fb64d16.png\" alt=\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 endpoint-\u0430 \/test\" title=\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 endpoint-\u0430 \/test\" width=\"600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c3d\/a12\/bdf\/c3da12bdfe14730cec2af47b7fb64d16.png\"\/><\/p>\n<div><figcaption>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 endpoint-\u0430 \/test<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0443 \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u044b \u0436\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u043b\u0438 \u0434\u043b\u044f swagger \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043f\u043e \u043f\u0443\u0442\u0438 <code>\/v3\/api-docs<\/code>, \u0430 \u0447\u0442\u043e\u0431\u044b \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b swagger \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u0441\u0435 endpoint-\u044b, \u043f\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 <code>\/**<\/code> \u0432 CORS \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438. \u0421\u0434\u0435\u043b\u0430\u0432 \u044d\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/0eb\/7a7\/bc8\/0eb7a7bc826fb0adc76489654bfdaf22.png\" alt=\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 endpoint-\u0430 \/test\" title=\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 endpoint-\u0430 \/test\" width=\"600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/0eb\/7a7\/bc8\/0eb7a7bc826fb0adc76489654bfdaf22.png\"\/><\/p>\n<div><figcaption>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 endpoint-\u0430 \/test<\/figcaption><\/div>\n<\/figure>\n<p>\u042d\u0442\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0440\u0435\u0448\u0438\u043b\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0441 CORS, \u043d\u043e \u043f\u043e\u0447\u0435\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0442\u0430\u043a \u0438 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a Authorization, \u0445\u043e\u0442\u044f \u043e\u043d \u0443\u043a\u0430\u0437\u0430\u043d? \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, swagger \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u0432 \u044f\u0432\u043d\u0443\u044e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438: <code>Content-Type<\/code>, <code>Accept<\/code>, <code>Authorization<\/code>. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 <a href=\"https:\/\/swagger.io\/docs\/specification\/describing-parameters\/#header-parameters\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>. \u041d\u043e \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0441\u0430\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0431\u0438\u043d\u0430 <code>OperationCustomizer customGlobalHeaders()<\/code> \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432.<\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0430\u0448\u0443 \u0437\u0430\u0434\u0430\u0447\u0443? \u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Springdoc \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u0442\u0430\u043c \u0435\u0441\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0435\u0441\u0442\u044c <a href=\"https:\/\/springdoc.org\/#how-do-i-add-authorization-header-in-requests\" rel=\"noopener noreferrer nofollow\">\u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0443\u0442\u044c<\/a>. \u0414\u043b\u044f \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430\u0448 \u0431\u0438\u043d <code>openAPI<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p><code><strong>RootAppConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @Configuration @RequiredArgsConstructor public class RootAppConfig {      @Value(\"${springdoc.auth.auth-header-enabled:false}\")     private Boolean authHeaderEnabled;      private final AppProperties.CorsProperties corsProperties;     private final BuildProperties buildProperties;      \/\/ ...      @Bean     public OpenAPI openAPI() {         String buildDate = buildProperties.get(\"build-date\");         String buildInfo = \"&lt;h4>Build date: \" + buildDate + \"&lt;\/h4>\"                 + \"&lt;br>\" + buildProperties.get(\"description\");          Components components = new Components();         List&lt;SecurityRequirement> securityRequirements = new ArrayList&lt;>();          \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c Authorization header         if (authHeaderEnabled) {             String securitySchemeName = \"Authorization header (Bearer)\";             components.addSecuritySchemes(securitySchemeName,                     new SecurityScheme()                             .type(SecurityScheme.Type.HTTP)                             .scheme(\"bearer\")             );             securityRequirements.add(new SecurityRequirement().addList(securitySchemeName));         }          return new OpenAPI()                 .components(components)                 .security(securityRequirements)                 .info(new Info()                         .title(buildProperties.getName())                         .description(buildInfo)                         .version(buildProperties.getVersion())                 );     } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0438 \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u043a\u043d\u043e\u043f\u043a\u0430 <code>Authorize<\/code>. \u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043d\u0435\u0435 \u0443 \u043d\u0430\u0441 \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 <code>Bearer<\/code> \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/8e2\/af3\/838\/8e2af383833f291afc24e7f6b7df69a7.png\" alt=\"\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Swagger UI\" title=\"\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Swagger UI\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/8e2\/af3\/838\/8e2af383833f291afc24e7f6b7df69a7.png\"\/><\/p>\n<div><figcaption>\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Swagger UI<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043d\u0430\u0448\u0435\u0433\u043e <code>test-client<\/code> \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/dc6\/6d7\/313\/dc66d73137ad7ecabe1aee874a53bb82.png\" alt=\"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 try it out \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c Bearer \u0442\u043e\u043a\u0435\u043d\u0430\" title=\"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 try it out \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c Bearer \u0442\u043e\u043a\u0435\u043d\u0430\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/dc6\/6d7\/313\/dc66d73137ad7ecabe1aee874a53bb82.png\"\/><\/p>\n<div><figcaption>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 try it out \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c Bearer \u0442\u043e\u043a\u0435\u043d\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0432\u044b\u0448\u0435 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 <code>Authorization<\/code> \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430.<\/p>\n<p>\u041d\u0443 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0438 \u0436\u0438\u0437\u043d\u044c \u0443\u0434\u0430\u043b\u0430\u0441\u044c, \u043d\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0443\u0434\u043e\u0431\u043d\u043e, \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u041f\u041e, \u0430 \u043f\u043e\u0442\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0435\u0433\u043e \u0441\u044e\u0434\u0430. \u0425\u043e\u0447\u0435\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0442\u0430\u043a \u0447\u0442\u043e\u0431\u044b \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435 <code>Authorize<\/code> \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0439\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c access \u0442\u043e\u043a\u0435\u043d. \u041a\u043e\u043f\u0430\u0432\u0448\u0438\u0441\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Swagger \u0438 Springdoc, \u044f \u0443\u0432\u0438\u0434\u0435\u043b, \u0447\u0442\u043e \u0438 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 OAuth 2 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443 Swagger UI, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430\u0448 \u0431\u0438\u043d <code>openAPI<\/code>. \u0412 \u043d\u0435\u0433\u043e \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b <code>SecurityScheme<\/code> \u0441 \u0442\u0438\u043f\u043e\u043c <code>SecurityScheme.Type.OAUTH2<\/code>. \u0414\u0430, \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f\u043e\u0432 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ol>\n<li>\n<p>Authorization code flow<\/p>\n<\/li>\n<li>\n<p>Client Credentials Flow<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0431\u0438\u043d <code>openAPI<\/code>:<\/p>\n<p><code><strong>RootAppConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @Configuration @RequiredArgsConstructor public class RootAppConfig {      private final AppProperties.CorsProperties corsProperties;     private final AppProperties.SwaggerProperties swaggerProperties;     private final BuildProperties buildProperties;      \/\/ ....      @Bean     public OpenAPI openAPI() {         String buildDate = buildProperties.get(\"build-date\");         String buildInfo = \"&lt;h4>Build date: \" + buildDate + \"&lt;\/h4>\"                 + \"&lt;br>\" + buildProperties.get(\"description\");          Components components = new Components();         List&lt;SecurityRequirement> securityRequirements = new ArrayList&lt;>();          \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c Authorization header         if (swaggerProperties.getAuthTypes().authHeaderEnabled()) {             String securitySchemeName = \"Authorization header\";             components.addSecuritySchemes(securitySchemeName,                     new SecurityScheme()                             .type(SecurityScheme.Type.HTTP)                             .scheme(\"bearer\")             );             securityRequirements.add(new SecurityRequirement().addList(securitySchemeName));         }          \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c OAuth2 Authorization code flow         if (swaggerProperties.getAuthTypes().authorizationCodeEnabled()) {             String securitySchemeName = \"Authorization code flow\";             components.addSecuritySchemes(securitySchemeName, new SecurityScheme()                     .type(SecurityScheme.Type.OAUTH2)                     .flows(new OAuthFlows().authorizationCode(                             new OAuthFlow()                                     .tokenUrl(swaggerProperties.getAuthOauth().tokenUrl())                                     .authorizationUrl(swaggerProperties.getAuthOauth().authorizationUrl())                                     .refreshUrl(swaggerProperties.getAuthOauth().refreshUrl())                     )));             securityRequirements.add(new SecurityRequirement().addList(securitySchemeName));         }          \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c OAuth2 Client credentials flow         if (swaggerProperties.getAuthTypes().clientCredentialsEnabled()) {             String securitySchemeName = \"Client credentials flow\";             components.addSecuritySchemes(securitySchemeName, new SecurityScheme()                     .type(SecurityScheme.Type.OAUTH2)                     .flows(new OAuthFlows().clientCredentials(                             new OAuthFlow().tokenUrl(swaggerProperties.getAuthOauth().tokenUrl())                     )));             securityRequirements.add(new SecurityRequirement().addList(securitySchemeName));         }          return new OpenAPI()                 .components(components)                 .security(securityRequirements)                 .info(new Info()                         .title(buildProperties.getName())                         .description(buildInfo)                         .version(buildProperties.getVersion())                 );     } } <\/code><\/pre>\n<p>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0435. \u041f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u043e\u0432\u044b\u0435 security \u0441\u0445\u0435\u043c\u044b \u0441 \u0442\u0438\u043f\u043e\u043c <code>SecurityScheme.Type.OAUTH2<\/code> \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c <code>OAuthFlows<\/code>.<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 <code>AppProperties.SwaggerProperties<\/code> \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 <code>AppProperties.CorsProperties<\/code>, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e Swagger \u0431\u044b\u043b\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0435\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.2\/j-sso\/src\/main\/java\/ru\/dlabs\/sas\/example\/jsso\/config\/AppProperties.java\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439, \u0432 \u0447\u0430\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a swagger, <code>application.yml<\/code> \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 <code>j-service<\/code> \u0438 <code>j-sso<\/code>.<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">\/\/ .....  springdoc:   auth-types:     auth-header-enabled: true     client-credentials-enabled: true     authorization-code-enabled: true   auth-oauth:     token-url: http:\/\/localhost:7777\/oauth2\/token     authorization_url: http:\/\/localhost:7777\/oauth2\/authorize     refresh-url: http:\/\/localhost:7777\/oauth2\/token   swagger-ui:     enabled: false   api-docs:     enabled: true     path: \/v3\/api-docs    \/\/ ..... <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u041d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/a3e\/ca5\/eb5\/a3eca5eb539ad54d7ca6302fbcbf4e51.png\" alt=\"\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Swagger UI\" title=\"\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u0430\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0430\u0437\u0446\u0438\u0438 Swagger UI\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/a3e\/ca5\/eb5\/a3eca5eb539ad54d7ca6302fbcbf4e51.png\"\/><\/p>\n<div><figcaption>\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u0430\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0430\u0437\u0446\u0438\u0438 Swagger UI<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u0441\u0435\u043a\u0446\u0438\u0438 Authorization code flow \u0432\u0432\u0435\u0434\u0435\u043c <code>client_id<\/code> \u0438 <code>client_secret<\/code> \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e <code>test-client<\/code> (\u0430 \u0438\u043c\u0435\u043d\u043d\u043e test-client\/test-client). \u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 <code>Authorize<\/code> \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 <code>j-sso<\/code>. \u041f\u0440\u043e\u0439\u0434\u0435\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/4da\/dfb\/913\/4dadfb9139341d0fffc2e75bacaa518f.png\" alt=\"Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" title=\"Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/4da\/dfb\/913\/4dadfb9139341d0fffc2e75bacaa518f.png\"\/><\/p>\n<div><figcaption>Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>redirect_uri<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 <code>\/oauth2\/authorize<\/code>. \u041a\u0441\u0442\u0430\u0442\u0438, \u0430 \u043a\u0430\u043a\u043e\u0439 \u043c\u044b <code>redirect_uri<\/code> \u0443\u043a\u0430\u0437\u0430\u043b\u0438, \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u0435\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c? \u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a <a href=\"https:\/\/springdoc.org\/properties.html\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 springdoc<\/a> \u0438 \u043d\u0430\u0439\u0434\u0435\u043c \u0442\u0430\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>springdoc.swagger-ui.oauth2RedirectUrl<\/code>. \u0412 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0442\u0430\u043c \u0443\u043a\u0430\u0437\u0430\u043d \u043f\u0443\u0442\u044c <code>\/swagger-ui\/oauth2-redirect.html<\/code>. \u0427\u0435\u0440\u0435\u0437 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c. \u041d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u043c\u044b \u0435\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043a\u0430 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0411\u0414 <code>sso.system_oauth2_clients<\/code> \u0440\u0443\u043a\u0430\u043c\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>http:\/\/localhost:7778\/swagger-ui\/oauth2-redirect.html<\/code> \u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 <code>redirect_uris<\/code> \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c.<\/p>\n<p>\u0418 \u0441\u043d\u043e\u0432\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443, \u043d\u043e \u0434\u0440\u0443\u0433\u0443\u044e.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/aa5\/401\/0b3\/aa54010b393ce3f4ad3b7fd046de431e.png\" alt=\"Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" title=\"Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/aa5\/401\/0b3\/aa54010b393ce3f4ad3b7fd046de431e.png\"\/><\/p>\n<div><figcaption>Stacktrace \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 <code>sso.system_oauth2_clients<\/code> \u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0443 <code>client_authentication_methods<\/code>. \u0421\u0435\u0439\u0447\u0430\u0441 \u0442\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>client_secret_basic<\/code>. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>client_secret<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 <code>Authorization<\/code> \u0441 \u0442\u0438\u043f\u043e\u043c <code>Basic<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a swagger \u0441\u0442\u0440\u043e\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 payload \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a <code>j-sso<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/3c1\/e1f\/4d3\/3c1e1f4d3fcf64489812cf4e13784645.png\" alt=\"Payload \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a j-sso\" title=\"Payload \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a j-sso\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/3c1\/e1f\/4d3\/3c1e1f4d3fcf64489812cf4e13784645.png\"\/><\/p>\n<div><figcaption>Payload \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a j-sso<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, swagger \u0432\u0441\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 POST. \u042f \u0438\u0441\u043a\u0430\u043b, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c swagger \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c <code>Authorization<\/code> \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u043d\u043e \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u0439\u0434\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u0443\u0442\u0435\u043c \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c <code>client_secret<\/code> \u0432 <code>form-data<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 <code>sso.system_oauth2_clients<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 <code>client_authentication_methods<\/code> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>client_secret_post<\/code>. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/6a4\/5de\/b09\/6a45deb0952673dae98b85a157dde901.png\" alt=\"\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 endpoint \/test\" title=\"\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 endpoint \/test\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/6a4\/5de\/b09\/6a45deb0952673dae98b85a157dde901.png\"\/><\/p>\n<div><figcaption>\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 endpoint \/test<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u0432\u044b\u0448\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 <code>\/test<\/code> \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 <code>j-service<\/code> \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u0412 \u0441\u0442\u0440\u043e\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u0438\u0434\u0435\u0442\u044c \u0447\u0442\u043e <code>Authorization<\/code> \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0438 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c 200-\u044b\u0439 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0443 swagger, \u043d\u043e \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0448\u0442\u0440\u0438\u0448\u043e\u043a. \u0421\u0435\u0439\u0447\u0430\u0441 \u0443 \u043d\u0430\u0441 \u0432\u0435\u0437\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 <code>test-client<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043b\u044f swagger \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u0441 \u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 \u0444\u0430\u0439\u043b <code>j-sso\/database\/release-1.0.0\/data\/system-oauth2-clients-data.sql<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 changeSet.<\/p>\n<p><code><strong>system-oauth2-clients-data.sql<\/strong><\/code><\/p>\n<pre><code class=\"sql\">--liquibase formatted sql  \/\/ ......  --changeSet daivanov:system-oauth2-clients-data-02 -- client_secret = swagger-client INSERT INTO sso.system_oauth2_clients(client_id, client_secret,                                       client_secret_expires_at,                                       client_name, client_authentication_methods,                                       authorization_grant_types, redirect_uris,                                       scopes, client_settings, token_settings) VALUES ('swagger-client', '$2a$10$G2AzJ0wujkRRbyU0hNWoNewpAfSPhg.cmo7HMT8cX9Xe6vdwmTMTW',         to_timestamp('2072-01-01', 'YYYY-MM-DD'), '\u041a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f Swagger UI',         'client_secret_post', 'authorization_code,refresh_token,client_credentials',         'http:\/\/localhost:7778\/swagger-ui\/oauth2-redirect.html', 'read.scope,write.scope', null, null); <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e swagger ui. \u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Swagger \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0435\u0433\u043e \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0432\u043c\u0435\u0441\u0442\u043e Postman.<\/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.2\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 3.3: \u041d\u0430\u0441\u0442\u0430\u043b \u0447\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 SSO<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0430\u0448\u0435\u0433\u043e <code>j-sso<\/code>. \u0412 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0438 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c VueJS. \u0412\u043e\u0442 \u0441 \u043d\u0435\u0433\u043e \u0438 \u043d\u0430\u0447\u043d\u0435\u043c.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0430\u043c\u043e VueJS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0415\u0433\u043e \u043c\u044b \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>j-sso\/client<\/code>. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c <a href=\"https:\/\/cli.vuejs.org\/guide\/creating-a-project.html\" rel=\"noopener noreferrer nofollow\"><code>vue-cli<\/code><\/a> (\u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u044f \u0443\u043a\u0430\u0437\u0430\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>vue 2<\/code>, <code>scss<\/code>, <code>vue-router<\/code> \u0438 <code>vuex<\/code>). \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0444\u043e\u0440\u043c\u044b \u043b\u043e\u0433\u0438\u043d\u0430 <code>j-sso<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u0442 Spring Security.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a <code>vue-cli<\/code> \u0441\u043e\u0437\u0434\u0430\u043b \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443 \u043d\u0430\u0441 \u0432 <code>package.json<\/code> \u0444\u0430\u0439\u043b\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u0432\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<ol>\n<li>\n<p><code>serve<\/code> &#8212; \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f dev server<\/p>\n<\/li>\n<li>\n<p><code>build<\/code> &#8212; \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ol>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0441 \u0441\u0435\u0439\u0447\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0431\u043e\u0440\u043a\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u0430 \u0444\u0430\u0439\u043b\u044b:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/49c\/417\/ab3\/49c417ab37d2a4416a72bf96b973665c.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043a\u0438 dist\" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043a\u0438 dist\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/49c\/417\/ab3\/49c417ab37d2a4416a72bf96b973665c.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043a\u0438 dist<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b <code>npm run build<\/code> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043b\u0430\u0441\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>dist<\/code> &#8212; \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 3 \u0447\u0430\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><code>index.html<\/code> &#8212; \u044d\u0442\u043e \u0433\u043b\u0430\u0432\u043d\u044b\u0439 html \u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>js<\/code> &#8212; \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0441\u043e \u0432\u0441\u0435\u043c JavaScript-\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0440\u043e\u0438\u0442 \u043d\u0430\u0448 UI.<\/p>\n<\/li>\n<li>\n<p>\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>css<\/code> &#8212; \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u0441\u0435 \u0441\u0442\u0438\u043b\u0438 <code>css<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443 \u043d\u0430\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u043a \u0436\u0435 \u043e\u043d\u0438 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0441\u0432\u044f\u0437\u0430\u043d\u044b? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 <code>index.html<\/code>, \u0432\u0435\u0434\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043c \u0438 \u0441\u043a\u0440\u044b\u0442 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441.<\/p>\n<p><code><strong>index.html<\/strong><\/code><\/p>\n<pre><code>&lt;!doctype html> &lt;html lang=\"\"> &lt;head>     &lt;meta charset=\"utf-8\">     &lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">     &lt;meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">     &lt;link rel=\"icon\" href=\"\/favicon.ico\">     &lt;title>client&lt;\/title>     &lt;script defer=\"defer\" src=\"\/js\/chunk-vendors.6bb41578.js\">&lt;\/script>     &lt;script defer=\"defer\" src=\"\/js\/app.5c0e5e95.js\">&lt;\/script>     &lt;link href=\"\/css\/app.bc18c568.css\" rel=\"stylesheet\"> &lt;\/head> &lt;body> &lt;noscript>&lt;strong>We're sorry but client doesn't work properly without JavaScript enabled. Please enable it to     continue.&lt;\/strong>&lt;\/noscript> &lt;div id=\"app\">&lt;\/div> &lt;\/body> &lt;\/html> <\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u044b \u043f\u043e\u043c\u043d\u0438\u043c \u0438\u0437 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0443\u0440\u043e\u043a\u043e\u0432 \u043f\u043e html, \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 <code>&lt;head><\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u043d\u0435\u043a\u0443\u044e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430: \u0441\u0442\u0438\u043b\u0438, \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u0448\u0440\u0438\u0444\u0442\u044b \u0438 \u0442.\u0434.<\/p>\n<blockquote>\n<p>\u0422\u0435\u0433  \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u0446\u0435\u043b\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u2014 \u043f\u043e\u043c\u043e\u0447\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0422\u0430\u043a\u0436\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430  \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043c\u0435\u0442\u0430\u0442\u0435\u0433\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 \u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043a \u043c\u0435\u0442\u0430\u0442\u0435\u0433\u0430\u043c \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0430\u0439\u0442\u0430, \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/blockquote>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u044d\u0442\u043e\u0433\u043e \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440\u0430 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 \u0442\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u0447\u043a\u0438. \u0412 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u0447\u043a\u0430\u0445 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 JavaScript-\u0430 \u0438 css \u0441\u0442\u0438\u043b\u0435\u0439 \u0438\u0437 \u0442\u0435\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439, \u0447\u0442\u043e \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0432\u044b\u0448\u0435. \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 \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u0438\u0437 web-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 (\u043a\u043e\u0438\u043c \u0443 \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Embedded Tomcat) \u043e\u0442\u0434\u0430\u0442\u044c \u044d\u0442\u043e\u0442 html \u0444\u0430\u0439\u043b \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u0438 \u0434\u0430\u043b\u0435\u0435 \u043e\u043d \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u0438\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0438 \u0441\u0442\u0438\u043b\u0438. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0430\u0448\u0435 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0410 \u044d\u0442\u043e \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0442\u0440\u0438 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c <code>j-sso<\/code> \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0438 endpoint, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c <code>index.html<\/code><\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448 <code>j-sso<\/code> \u0443\u043c\u0435\u043b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441\u044b (<code>js<\/code>, <code>css<\/code>, <code>images<\/code> \u0438 \u0442.\u0434.) \u043f\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u0438\u0437 <code>index.html<\/code><\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u0432\u0438\u0434\u043e\u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043e <code>js<\/code> \u0438 <code>css<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0439\u0442\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0443\u0442\u0435\u0439 \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ol>\n<h4>\u0420\u0435\u0448\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443<\/h4>\n<p>\u0414\u043b\u044f \u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0440\u043e <a href=\"https:\/\/spring.io\/guides\/gs\/serving-web-content\/\" rel=\"noopener noreferrer nofollow\">Spring MVC<\/a> \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0430\u043a \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0437\u0430\u0434\u0430\u0447\u0443. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0432\u0441\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0438\u043c\u044f html \u0444\u0430\u0439\u043b\u0430. \u0414\u0430\u043d\u043d\u044b\u0439 html \u0444\u0430\u0439\u043b, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>templates<\/code>. \u041d\u043e, \u0432\u0441\u0435 \u044d\u0442\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0435\u0437 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 <a href=\"https:\/\/www.tutorialspoint.com\/spring_boot\/spring_boot_thymeleaf.htm\" rel=\"noopener noreferrer nofollow\"><code>spring-boot-starter-thymeleaf<\/code><\/a>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432 <code>j-sso<\/code> \u043c\u043e\u0434\u0443\u043b\u044c.<\/p>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ ....      &lt;dependencies>          &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-starter-thymeleaf&lt;\/artifactId>         &lt;\/dependency>      &lt;\/dependencies>      \/\/ .... &lt;\/project> <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u043d\u0430\u0448 <code>index.html<\/code> \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>client\/dist<\/code> \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>resources\/templates<\/code>. \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 url \u0438\u0437 security \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 (\u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043c\u0435\u0448\u0430\u043b\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043c).<\/p>\n<p><code><strong>UIController.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Controller public class UIController {      @GetMapping(\"\/ui-test\")     public String index() {         return \"index\";     } } <\/code><\/pre>\n<p>\u0421\u043e\u0431\u0435\u0440\u0435\u043c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c <code>j-sso<\/code> \u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043d\u0430 URL <code>http:\/\/localhost:7777\/ui-test<\/code>. \u041c\u044b \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0443\u0432\u0438\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0431\u0435\u043b\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u043e \u043d\u0430\u0441 \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442. \u041d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435: \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u0438\u043b\u0441\u044f \u043b\u0438 \u043d\u0430\u0448 <code>index.html<\/code> \u0444\u0430\u0439\u043b? \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043e\u0442\u0432\u0435\u0442 GET \u0437\u0430\u043f\u0440\u043e\u0441\u0430 <code>\/ui-test<\/code>. \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u043d\u0438\u0436\u0435, \u043d\u0430\u0448 <code>index.html<\/code> \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u0438\u043b\u0441\u044f. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0432\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/3ee\/3c1\/60c\/3ee3c160c35c625ab91dd0ebaf2b355b.png\" alt=\"\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0430\u0439\u043b\u0430 index.html \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435\" title=\"\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0430\u0439\u043b\u0430 index.html \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/3ee\/3c1\/60c\/3ee3c160c35c625ab91dd0ebaf2b355b.png\"\/><\/p>\n<div><figcaption>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0430\u0439\u043b\u0430 index.html \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435<\/figcaption><\/div>\n<\/figure>\n<h4>\u0420\u0435\u0448\u0430\u0435\u043c \u0432\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443<\/h4>\n<p>\u041d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f <code>js<\/code> \u0438 <code>css<\/code> \u0444\u0430\u0439\u043b\u044b. \u041f\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0443\u0442\u0438 \u043e\u043d\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438, \u043a\u0430\u043a \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0448\u0438\u043c \u0437\u0430\u0434\u0430\u0447\u0443 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0434\u043b\u044f Embedded Tomcat, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0448\u0438\u0442 \u0432 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 <code>j-sso<\/code>.<\/p>\n<p>\u0418\u0437 <a href=\"https:\/\/spring.io\/blog\/2013\/12\/19\/serving-static-web-content-with-spring-boot\" rel=\"noopener noreferrer nofollow\">\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430 Spring<\/a> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0439\u0442\u0438, \u0447\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0432 \u043e\u0434\u043d\u0443 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0438 \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u0443\u0442\u044f\u043c:<\/p>\n<ul>\n<li>\n<p><code>\/META-INF\/resources\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>\/resources\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>\/static\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>\/public\/<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>client\/dist<\/code> \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>src\/main\/resources\/static<\/code>. \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b Security \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432: <code>\/favicon.ico<\/code>, <code>\/js\/**<\/code>, <code>\/css\/**<\/code>.<\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u0441\u0442\u0430\u043b\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0438\u0437 \u043f\u043e\u0434 security, \u0430 \u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0432 \u0434\u0432\u0443\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430\u0445 (<code>SecurityConfig<\/code> \u0438 <code>AuthorizationServerConfig<\/code>) \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u0442\u043e \u0432 <code>SecurityConfig<\/code> \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443, \u0430 \u0432 <code>AuthorizationServerConfig<\/code> \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c:<\/p>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> public class SecurityConfig {      public static final String[] PERMIT_ALL_PATTERNS = {             \"\/v3\/api-docs\",             \"\/ui-test\",             \"\/favicon.ico\",             \"\/js\/**\",             \"\/css\/**\"     };      \/\/ ....      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         SocialConfigurer socialConfigurer = new SocialConfigurer()                 .oAuth2UserService(customOAuth2UserService);         http.apply(socialConfigurer);          http.getSharedObject(AuthenticationManagerBuilder.class)                 .userDetailsService(userDetailService)                 .passwordEncoder(passwordEncoder);          http.authorizeHttpRequests(authorize ->                 authorize                         \/\/ endpoint-\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0438\u0437 \u043f\u043e\u0434 security                         .requestMatchers(PERMIT_ALL_PATTERNS).permitAll()                         .anyRequest().authenticated()         );         return http.formLogin(withDefaults()).build();     } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0435\u0440\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c. \u0414\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043d\u0430 URL <code>http:\/\/localhost:7777\/ui-test<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/401\/56f\/c47\/40156fc4711e0729e607299a49fdad7d.png\" alt=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 VueJS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Embedded Tomcat\" title=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 VueJS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Embedded Tomcat\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/401\/56f\/c47\/40156fc4711e0729e607299a49fdad7d.png\"\/><\/p>\n<div><figcaption>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 VueJS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Embedded Tomcat<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u0432\u044b\u0448\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0438\u0441\u044c \u0438 \u043d\u0430\u0448\u0435 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e.<\/p>\n<p>\u041d\u043e \u044d\u0442\u043e \u0435\u0449\u0435 \u043d\u0435 \u0432\u0441\u0435. \u041c\u043d\u0435 \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0438\u043c\u0435\u044e\u0442 URL \u043e\u0442 \u043a\u043e\u0440\u043d\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u044d\u0442\u043e \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0442\u0440\u0443\u0434\u043d\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0445\u043e\u0447\u0443 \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0438\u043c\u0435\u043b\u0438 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 <code>\/static\/**<\/code>.<\/p>\n<p>\u0412 Spring Boot \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e: \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>spring.mvc.static-path-pattern<\/code>. \u041a\u0441\u0442\u0430\u0442\u0438, \u0432 Spring Boot \u044f \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0448\u0435\u043b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0434\u043b\u044f \u044f\u0432\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 &#8212; <code>spring.web.resources.static-locations<\/code>.<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">\/\/ .... spring:   application:     name: j-sso   mvc:     static-path-pattern: \/static\/**     cors:       configs:         - pattern: \/**           allowed-origins: \"http:\/\/127.0.0.1:8080,http:\/\/localhost:8080,http:\/\/localhost:7778\"           allowed-headers: \"*\"           exposed-headers: \"*\"           allowed-methods: \"*\"           allow-credentials: true   web:     resources:       static-locations: classpath:static    \/\/ .... <\/code><\/pre>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b security \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 <code>\/static\/**<\/code>, \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0442\u0435\u043f\u0435\u0440\u044c front \u0443 \u043d\u0430\u0441 \u0441\u043b\u043e\u043c\u0430\u043d, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e html \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c <code>js<\/code> \u0438 <code>css<\/code> \u043f\u043e \u0441\u0442\u0430\u0440\u044b\u043c \u043f\u0443\u0442\u044f\u043c (\u043e\u0442 \u043a\u043e\u0440\u043d\u044f), \u0430 <code>js<\/code> \u0438 <code>css<\/code> \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043f\u043e \u043d\u043e\u0432\u043e\u043c\u0443 \u043f\u0443\u0442\u0438. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 <code>favicon.ico<\/code> \u043f\u043e \u043f\u0443\u0442\u0438 <code>http:\/\/localhost:7777\/static\/favicon.ico<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/713\/318\/c98\/713318c986cdc4b41466c9e8f0118e70.png\" alt=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 favicon.ico \u043f\u043e \u043d\u043e\u0432\u043e\u043c\u0443 \u043f\u0443\u0442\u0438\" title=\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 favicon.ico \u043f\u043e \u043d\u043e\u0432\u043e\u043c\u0443 \u043f\u0443\u0442\u0438\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/713\/318\/c98\/713318c986cdc4b41466c9e8f0118e70.png\"\/><\/p>\n<div><figcaption>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 favicon.ico \u043f\u043e \u043d\u043e\u0432\u043e\u043c\u0443 \u043f\u0443\u0442\u0438<\/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 \u0432\u0441\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e. \u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435.<\/p>\n<h4>\u0420\u0435\u0448\u0430\u0435\u043c \u0442\u0440\u0435\u0442\u044c\u044e \u0437\u0430\u0434\u0430\u0447\u0443<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u044f\u0442\u044c \u043e\u043a\u0443\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u043c\u0438\u0440 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 <code>Webpack<\/code>. \u0412 <code>Webpack<\/code> \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>output.publicPath<\/code> (<a href=\"https:\/\/webpack.js.org\/guides\/public-path\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e<\/a>). \u0410 \u043a\u0430\u043a \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c vue \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438? \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 <code>vue.config.js<\/code>. \u0417\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 <a href=\"https:\/\/cli.vuejs.org\/ru\/config\/#publicpath\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e vue-cli<\/a> \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u0440\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>publicPath<\/code>.<\/p>\n<blockquote>\n<p>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 URL-\u0430\u0434\u0440\u0435\u0441 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e (\u0438\u043c\u0435\u043d\u0443\u0435\u043c\u0430\u044f \u043a\u0430\u043a baseUrl \u0434\u043e \u0432\u0435\u0440\u0441\u0438\u0438 Vue CLI 3.3). \u042d\u0442\u043e \u0430\u043d\u0430\u043b\u043e\u0433 \u043e\u043f\u0446\u0438\u0438 webpack output.publicPath, \u043d\u043e Vue CLI \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u0446\u0435\u043b\u044f\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c publicPath \u0432\u043c\u0435\u0441\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0446\u0438\u0438 output.publicPath.<\/p>\n<\/blockquote>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432 <code>vue.config.js<\/code> \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0442\u0430\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>\/static<\/code>.<\/p>\n<p><code><strong>vue.config.js<\/strong><\/code><\/p>\n<pre><code>const {defineConfig} = require('@vue\/cli-service');  module.exports = defineConfig({     transpileDependencies: true,     publicPath: process.env.VUE_APP_NODE_ENV !== \"development\" ? \"\/static\" : \"\", }); <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u043c\u044b \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u043f\u0443\u0442\u044c, \u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0442\u0435\u0440\u043d\u0430\u0440\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0430\u0432\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code>VUE_APP_NODE_ENV<\/code> \u043d\u0435 \u0440\u0430\u0432\u043d\u0430 <code>development<\/code>. \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 vue \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e (\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044f \u0435\u0433\u043e \u043d\u0430 node \u0441\u0435\u0440\u0432\u0435\u0440\u0435). \u0414\u0430\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 <code>.env<\/code> \u0444\u0430\u0439\u043b\u0430\u0445. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c 4 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<ul>\n<li>\n<p><code>.env.development<\/code> &#8212; \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0441\u0440\u0435\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code>.env.production<\/code> &#8212; \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b<\/p>\n<\/li>\n<li>\n<p><code>.env.testing<\/code> &#8212; \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0441\u0440\u0435\u0434\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code>.env.dev-java<\/code> &#8212; \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0441\u0440\u0435\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 (\u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438)<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043d\u0438\u0445 \u0443\u043a\u0430\u0436\u0435\u043c \u043f\u043e\u043a\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>VUE_APP_NODE_ENV<\/code> \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430. \u0422\u0435\u043f\u0435\u0440\u044c, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c <code>process.env.VUE_APP_NODE_ENV<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0432 <code>package.json<\/code>.<\/p>\n<p><code><strong>package.json<\/strong><\/code><\/p>\n<pre><code class=\"json\">{   \"name\": \"client\",   \"version\": \"0.1.0\",   \"private\": true,   \"scripts\": {     \"serve\": \"vue-cli-service serve --mode=development\",     \"build\": \"vue-cli-service build --mode=development\",     \"build-prod\": \"vue-cli-service build --mode=production\",     \"build-test\": \"vue-cli-service build --mode=testing\",     \"build-dev-java\": \"vue-cli-service build --mode=dev-java\"   }   \/\/ ..... } <\/code><\/pre>\n<p>\u0421\u043e\u0431\u0435\u0440\u0435\u043c \u043d\u0430\u0448\u0435 Vue.js \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>npm run build-prod<\/code> \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 <code>index.html<\/code>.<\/p>\n<p><code><strong>index.html<\/strong><\/code><\/p>\n<pre><code>&lt;!doctype html> &lt;html lang=\"\"> &lt;head>     &lt;meta charset=\"utf-8\">     &lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">     &lt;meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">     &lt;link rel=\"icon\" href=\"\/static\/favicon.ico\">     &lt;title>client&lt;\/title>     &lt;script defer=\"defer\" src=\"\/static\/js\/chunk-vendors.efbb0edb.js\">&lt;\/script>     &lt;script defer=\"defer\" src=\"\/static\/js\/app.41afe825.js\">&lt;\/script>     &lt;link href=\"\/static\/css\/app.bc18c568.css\" rel=\"stylesheet\"> &lt;\/head> &lt;body> &lt;noscript>&lt;strong>We're sorry but client doesn't work properly without JavaScript enabled. Please enable it to     continue.&lt;\/strong>&lt;\/noscript> &lt;div id=\"app\">&lt;\/div> &lt;\/body> &lt;\/html> <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u044b\u0448\u0435, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438, \u0447\u0442\u043e \u0445\u043e\u0442\u0435\u043b\u0438. \u0422\u0430\u043a\u0436\u0435, \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0447\u0435\u0440\u0435\u0437 <code>npm run serve<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0442\u043e\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<p>\u041f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0441\u0431\u043e\u0440\u043a\u0443 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u043d\u0430\u0448\u0435\u0433\u043e <code>j-sso<\/code>. \u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, UI \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.<\/p>\n<h4>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438<\/h4>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0438 \u0437\u0430\u043d\u043e\u0432\u043e \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b <code>j-sso<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e. \u0415\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0443\u0442\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e: \u0441\u043e\u0437\u0434\u0430\u0442\u044c bash \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Docker \u0438 \u0442.\u0434. \u041d\u043e \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e maven \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u0432\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430:<\/p>\n<ul>\n<li>\n<p><code>com.github.eirslett:frontend-maven-plugin<\/code> &#8212; \u043e\u043d \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f npm \u0437\u0430\u0434\u0430\u0447. \u0422\u0430\u043a\u0436\u0435 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Node \u0438 NPM \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u0445 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438. \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/eirslett\/frontend-maven-plugin\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<li>\n<p><code>org.apache.maven.plugins:maven-resources-plugin<\/code> &#8212; \u0434\u0430\u043d\u043d\u044b\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438\u0437 <code>client\/dist<\/code> \u0432 <code>target<\/code>. \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/maven.apache.org\/plugins\/maven-resources-plugin\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d <code>frontend-maven-plugin<\/code>:<\/p>\n<ol>\n<li>\n<p><code>install node and npm<\/code> &#8212; \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 Node \u0438 NPM \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><code>npm install<\/code> &#8212; \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><code>npm build<\/code> &#8212; \u0441\u0431\u043e\u0440\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u0430<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d <code>maven-resources-plugin<\/code>:<\/p>\n<ol>\n<li>\n<p><code>copy-to-templates<\/code> &#8212; \u0437\u0430\u0434\u0430\u0447\u0430 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <code>index.html<\/code> \u0444\u0430\u0439\u043b\u0430 \u0438\u0437 <code>client\/dist<\/code> \u0432 <code>target\/classes\/templates<\/code><\/p>\n<\/li>\n<li>\n<p><code>copy-to-static<\/code> &#8212; \u0437\u0430\u0434\u0430\u0447\u0430 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437 <code>client\/dist<\/code> \u0432 <code>target\/classes\/static<\/code><\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>j-sso\/pom.xml<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">     &lt;parent>         &lt;artifactId>spring-authorization-server-example&lt;\/artifactId>         &lt;groupId>ru.dlabs&lt;\/groupId>         &lt;version>0.0.1&lt;\/version>     &lt;\/parent>     &lt;modelVersion>4.0.0&lt;\/modelVersion>      &lt;artifactId>j-sso&lt;\/artifactId>     &lt;name>SSO Server&lt;\/name>     &lt;description>\u0415\u0434\u0438\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \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\u0435\u0439&lt;\/description>      &lt;properties>         &lt;maven.compiler.source>17&lt;\/maven.compiler.source>         &lt;maven.compiler.target>17&lt;\/maven.compiler.target>         &lt;build-date>${maven.build.timestamp}&lt;\/build-date>         &lt;maven.build.timestamp.format>yyyy-MM-dd HH:mm&lt;\/maven.build.timestamp.format>     &lt;\/properties>      \/\/ ......      &lt;build>         &lt;finalName>${project.artifactId}&lt;\/finalName>         &lt;plugins>             &lt;plugin>                 &lt;groupId>com.github.eirslett&lt;\/groupId>                 &lt;artifactId>frontend-maven-plugin&lt;\/artifactId>                 &lt;executions>                     &lt;!-- \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 Node \u0438 NPM \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u0430-->                     &lt;execution>                         &lt;id>install node and npm&lt;\/id>                         &lt;goals>                             &lt;goal>install-node-and-npm&lt;\/goal>                         &lt;\/goals>                         &lt;phase>generate-resources&lt;\/phase>                     &lt;\/execution>                     &lt;!-- \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0430-->                     &lt;execution>                         &lt;id>npm install&lt;\/id>                         &lt;goals>                             &lt;goal>npm&lt;\/goal>                         &lt;\/goals>                         &lt;phase>generate-resources&lt;\/phase>                         &lt;configuration>                             &lt;workingDirectory>client&lt;\/workingDirectory>                             &lt;arguments>install&lt;\/arguments>                         &lt;\/configuration>                     &lt;\/execution>                     &lt;!-- \u0421\u0431\u043e\u0440\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u0430-->                     &lt;execution>                         &lt;id>npm build&lt;\/id>                         &lt;goals>                             &lt;goal>npm&lt;\/goal>                         &lt;\/goals>                         &lt;phase>generate-resources&lt;\/phase>                         &lt;configuration>                             &lt;workingDirectory>client&lt;\/workingDirectory>                             &lt;arguments>run build-dev-java&lt;\/arguments>                         &lt;\/configuration>                     &lt;\/execution>                 &lt;\/executions>                 &lt;configuration>                     &lt;nodeVersion>v16.20.1&lt;\/nodeVersion>                     &lt;npmVersion>9.7.2&lt;\/npmVersion>                     &lt;nodeDownloadRoot>https:\/\/nodejs.org\/dist\/&lt;\/nodeDownloadRoot>                     &lt;npmDownloadRoot>https:\/\/registry.npmjs.org\/npm\/-\/&lt;\/npmDownloadRoot>                     &lt;installDirectory>.node&lt;\/installDirectory>                 &lt;\/configuration>             &lt;\/plugin>             &lt;plugin>                 &lt;groupId>org.apache.maven.plugins&lt;\/groupId>                 &lt;artifactId>maven-resources-plugin&lt;\/artifactId>                 &lt;executions>                     &lt;!-- \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 index.html \u0444\u0430\u0439\u043b\u0430 \u0438\u0437 client\/dist \u0432 target\/classes\/templates-->                     &lt;execution>                         &lt;id>copy-templates&lt;\/id>                         &lt;phase>generate-resources&lt;\/phase>                         &lt;goals>                             &lt;goal>copy-resources&lt;\/goal>                         &lt;\/goals>                         &lt;configuration>                             &lt;outputDirectory>${basedir}\/target\/classes\/templates&lt;\/outputDirectory>                             &lt;resources>                                 &lt;resource>                                     &lt;directory>${basedir}\/client\/dist&lt;\/directory>                                     &lt;includes>                                         &lt;include>index.html&lt;\/include>                                     &lt;\/includes>                                 &lt;\/resource>                             &lt;\/resources>                         &lt;\/configuration>                     &lt;\/execution>                     &lt;!-- \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 js, css, images \u0438 \u0442.\u0434. \u0438\u0437 client\/dist \u0432 target\/classes\/static-->                     &lt;execution>                         &lt;id>copy-static&lt;\/id>                         &lt;phase>generate-resources&lt;\/phase>                         &lt;goals>                             &lt;goal>copy-resources&lt;\/goal>                         &lt;\/goals>                         &lt;configuration>                             &lt;outputDirectory>${basedir}\/target\/classes\/static&lt;\/outputDirectory>                             &lt;resources>                                 &lt;resource>                                     &lt;directory>${basedir}\/client\/dist&lt;\/directory>                                     &lt;includes>                                         &lt;include>favicon.ico&lt;\/include>                                         &lt;include>js\/**&lt;\/include>                                         &lt;include>css\/**&lt;\/include>                                     &lt;\/includes>                                 &lt;\/resource>                             &lt;\/resources>                         &lt;\/configuration>                     &lt;\/execution>                 &lt;\/executions>             &lt;\/plugin>         &lt;\/plugins>     &lt;\/build> &lt;\/project> <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0441\u0431\u043e\u0440\u043a\u0438 java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u0441\u0442\u0432:<\/p>\n<ol>\n<li>\n<p>\u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c Node \u0438 npm \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0441\u043a\u0430\u0447\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u0431\u043e\u0440\u043a\u0443, \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u043b\u043e\u0441\u044c, \u0431\u0435\u0441\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043a\u043e\u0433\u0434\u0430 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0423 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c 3 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438: development, test \u0438 production. \u0412 Java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u0442\u043e\u0436\u0435 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0438. \u041d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u0443\u044e \u0438 \u0432\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c\/\u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443. \u041c\u044b \u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e Maven \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 (execution) \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 build phase. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043a\u043e\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 <code>&lt;phase><\/code> \u0438 \u0432 \u043d\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c\/\u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0441\u043c\u0435\u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>phase<\/code> \u0443 <code>execution<\/code>. \u041d\u043e \u043a\u0430\u043a \u043c\u044b \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c?<\/p>\n<p>\u0418 \u0442\u0443\u0442 \u043d\u0430 \u0441\u0446\u0435\u043d\u0443 \u0432\u044b\u0445\u043e\u0434\u044f\u0442 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 maven \u0438 <code>&lt;properties><\/code>. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 <code>properties<\/code>:<\/p>\n<ol>\n<li>\n<p><code>build-client.phrase<\/code> &#8212; \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>phase<\/code> \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u043e \u0441\u0431\u043e\u0440\u043a\u0430 \u043d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0431\u0435\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Node \u0438 NPM, \u0435\u0441\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u043e\u043d\u0438 \u043d\u0435 \u0431\u044b\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b. \u0422\u0430\u043a\u0436\u0435, \u0441\u0431\u043e\u0440\u043a\u0430 \u043d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u044b\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u0437\u0430\u043f\u0443\u0441\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Node \u0438 NPM, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u043e\u0434 \u043e\u0434\u0438\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440. \u041a\u0441\u0442\u0430\u0442\u0438, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 Node \u0438 NPM \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b. \u0417\u0434\u0435\u0441\u044c \u0437\u0430 \u043d\u0430\u0441 \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p><code>copy-client-build.phrase<\/code> &#8212; \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>phase<\/code> \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 <code>target<\/code> \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p><code>client-build-command.param<\/code> &#8212; \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (<code>build-prod<\/code>, <code>build<\/code>, <code>build-test<\/code>)<\/p>\n<\/li>\n<\/ol>\n<p>\u0418 \u0434\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 maven, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0430 \u0447\u0442\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0438:<\/p>\n<ul>\n<li>\n<p><code>dev<\/code> &#8212; \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0441\u0440\u0435\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0430\u043a\u0442\u0438\u0432\u0435\u043d<\/p>\n<\/li>\n<li>\n<p><code>test<\/code> &#8212; \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0441\u0440\u0435\u0434\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code>prod<\/code> &#8212; \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><code>client-build-and-copy<\/code> &#8212; \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0435\u0442 \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u0430 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0441\u0431\u043e\u0440\u043a\u0438 java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code>client-only-copy<\/code> &#8212; \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u0430 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0441\u0431\u043e\u0440\u043a\u0438 java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0444\u0430\u0439\u043b <code>pom.xml<\/code> \u0434\u043b\u044f <code>j-sso<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>j-sso\/pom.xml<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">     &lt;parent>         &lt;artifactId>spring-authorization-server-example&lt;\/artifactId>         &lt;groupId>ru.dlabs&lt;\/groupId>         &lt;version>0.0.1&lt;\/version>     &lt;\/parent>     &lt;modelVersion>4.0.0&lt;\/modelVersion>      &lt;artifactId>j-sso&lt;\/artifactId>     &lt;name>SSO Server&lt;\/name>     &lt;description>\u0415\u0434\u0438\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \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\u0435\u0439&lt;\/description>      &lt;properties>         &lt;maven.compiler.source>17&lt;\/maven.compiler.source>         &lt;maven.compiler.target>17&lt;\/maven.compiler.target>         &lt;build-date>${maven.build.timestamp}&lt;\/build-date>         &lt;maven.build.timestamp.format>yyyy-MM-dd HH:mm&lt;\/maven.build.timestamp.format>          &lt;build-client.phrase>disabled&lt;\/build-client.phrase>         &lt;copy-client-build.phrase>disabled&lt;\/copy-client-build.phrase>         &lt;client-build-command.param>build-dev-java&lt;\/client-build-command.param>     &lt;\/properties>      \/\/ ......      &lt;profiles>         &lt;!-- \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f-->         &lt;profile>             &lt;id>client-build-and-copy&lt;\/id>             &lt;properties>                 &lt;build-client.phrase>generate-resources&lt;\/build-client.phrase>                 &lt;copy-client-build.phrase>generate-resources&lt;\/copy-client-build.phrase>             &lt;\/properties>         &lt;\/profile>         &lt;!-- \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u0434\u043b\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f-->         &lt;profile>             &lt;id>client-only-copy&lt;\/id>             &lt;properties>                 &lt;build-client.phrase>non&lt;\/build-client.phrase>                 &lt;copy-client-build.phrase>generate-resources&lt;\/copy-client-build.phrase>             &lt;\/properties>         &lt;\/profile>         &lt;!-- \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f dev \u0441\u0440\u0435\u0434\u044b, \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0430\u043a\u0442\u0438\u0432\u0435\u043d-->         &lt;profile>             &lt;id>dev&lt;\/id>             &lt;activation>                 &lt;activeByDefault>true&lt;\/activeByDefault>             &lt;\/activation>             &lt;properties>                 &lt;client-build-command.param>build-dev-java&lt;\/client-build-command.param>             &lt;\/properties>         &lt;\/profile>         &lt;!-- \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f test \u0441\u0440\u0435\u0434\u044b-->         &lt;profile>             &lt;id>test&lt;\/id>             &lt;properties>                 &lt;client-build-command.param>build-test&lt;\/client-build-command.param>             &lt;\/properties>         &lt;\/profile>         &lt;!-- \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f production \u0441\u0440\u0435\u0434\u044b-->         &lt;profile>             &lt;id>prod&lt;\/id>             &lt;properties>                 &lt;client-build-command.param>build-prod&lt;\/client-build-command.param>             &lt;\/properties>         &lt;\/profile>     &lt;\/profiles>      &lt;build>         &lt;finalName>${project.artifactId}&lt;\/finalName>         &lt;plugins>             &lt;plugin>                 &lt;groupId>com.github.eirslett&lt;\/groupId>                 &lt;artifactId>frontend-maven-plugin&lt;\/artifactId>                 &lt;executions>                     &lt;!-- \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 Node \u0438 NPM \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u0430-->                     &lt;execution>                         &lt;id>install node and npm&lt;\/id>                         &lt;goals>                             &lt;goal>install-node-and-npm&lt;\/goal>                         &lt;\/goals>                         &lt;phase>${build-client.phrase}&lt;\/phase>                     &lt;\/execution>                     &lt;!-- \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0430-->                     &lt;execution>                         &lt;id>npm install&lt;\/id>                         &lt;goals>                             &lt;goal>npm&lt;\/goal>                         &lt;\/goals>                         &lt;phase>${build-client.phrase}&lt;\/phase>                         &lt;configuration>                             &lt;workingDirectory>client&lt;\/workingDirectory>                             &lt;arguments>install&lt;\/arguments>                         &lt;\/configuration>                     &lt;\/execution>                     &lt;!-- \u0421\u0431\u043e\u0440\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u0430-->                     &lt;execution>                         &lt;id>npm build&lt;\/id>                         &lt;goals>                             &lt;goal>npm&lt;\/goal>                         &lt;\/goals>                         &lt;phase>${build-client.phrase}&lt;\/phase>                         &lt;configuration>                             &lt;workingDirectory>client&lt;\/workingDirectory>                             &lt;arguments>run ${client-build-command.param}&lt;\/arguments>                         &lt;\/configuration>                     &lt;\/execution>                 &lt;\/executions>                 &lt;configuration>                     &lt;nodeVersion>v16.20.1&lt;\/nodeVersion>                     &lt;npmVersion>9.7.2&lt;\/npmVersion>                     &lt;nodeDownloadRoot>https:\/\/nodejs.org\/dist\/&lt;\/nodeDownloadRoot>                     &lt;npmDownloadRoot>https:\/\/registry.npmjs.org\/npm\/-\/&lt;\/npmDownloadRoot>                     &lt;installDirectory>.node&lt;\/installDirectory>                 &lt;\/configuration>             &lt;\/plugin>             &lt;plugin>                 &lt;groupId>org.apache.maven.plugins&lt;\/groupId>                 &lt;artifactId>maven-resources-plugin&lt;\/artifactId>                 &lt;executions>                     &lt;!-- \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 index.html \u0444\u0430\u0439\u043b\u0430 \u0438\u0437 client\/dist \u0432 target\/classes\/templates-->                     &lt;execution>                         &lt;id>copy-templates&lt;\/id>                         &lt;phase>${copy-client-build.phrase}&lt;\/phase>                         &lt;goals>                             &lt;goal>copy-resources&lt;\/goal>                         &lt;\/goals>                         &lt;configuration>                             &lt;outputDirectory>${basedir}\/target\/classes\/templates&lt;\/outputDirectory>                             &lt;resources>                                 &lt;resource>                                     &lt;directory>${basedir}\/client\/dist&lt;\/directory>                                     &lt;includes>                                         &lt;include>index.html&lt;\/include>                                     &lt;\/includes>                                 &lt;\/resource>                             &lt;\/resources>                         &lt;\/configuration>                     &lt;\/execution>                     &lt;!-- \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 js, css, images \u0438 \u0442.\u0434. \u0438\u0437 client\/dist \u0432 target\/classes\/static-->                     &lt;execution>                         &lt;id>copy-static&lt;\/id>                         &lt;phase>${copy-client-build.phrase}&lt;\/phase>                         &lt;goals>                             &lt;goal>copy-resources&lt;\/goal>                         &lt;\/goals>                         &lt;configuration>                             &lt;outputDirectory>${basedir}\/target\/classes\/static&lt;\/outputDirectory>                             &lt;resources>                                 &lt;resource>                                     &lt;directory>${basedir}\/client\/dist&lt;\/directory>                                     &lt;includes>                                         &lt;include>favicon.ico&lt;\/include>                                         &lt;include>js\/**&lt;\/include>                                         &lt;include>css\/**&lt;\/include>                                     &lt;\/includes>                                 &lt;\/resource>                             &lt;\/resources>                         &lt;\/configuration>                     &lt;\/execution>                 &lt;\/executions>             &lt;\/plugin>         &lt;\/plugins>     &lt;\/build> &lt;\/project> <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>clean install -DskipTests -P dev,client-build-and-copy<\/code> \u043c\u044b \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u043a\u0430\u043a frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0442\u0430\u043a \u0438 backend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e SSO. \u0410 \u043f\u043e\u043c\u0435\u043d\u044f\u0432 \u043f\u0440\u043e\u0444\u0438\u043b\u044c <code>clean install -DskipTests -P dev,client-only-copy<\/code> \u043c\u044b \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b\u044b \u0441\u0431\u043e\u0440\u043a\u0438 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 <code>target<\/code> \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0438 \u0441\u043e\u0431\u0435\u0440\u0435\u043c java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c, \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>resources<\/code> \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0435 \u0444\u0430\u0439\u043b\u044b \u0441\u0431\u043e\u0440\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u043b\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 IntelliJ IDEA, \u0442\u043e \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u0443\u043a\u0430\u0437\u0430\u0432 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u0431\u043e\u0440\u043a\u0438. \u0418\u043d\u0430\u0447\u0435, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0444\u0440\u043e\u043d\u0442.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/449\/2cd\/c5d\/4492cdc5d4dc89440b8a0d2bc8f279e0.png\" alt=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 j-sso \u0432 IntelliJ IDEA\" title=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 j-sso \u0432 IntelliJ IDEA\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/449\/2cd\/c5d\/4492cdc5d4dc89440b8a0d2bc8f279e0.png\"\/><\/p>\n<div><figcaption>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 j-sso \u0432 IntelliJ IDEA<\/figcaption><\/div>\n<\/figure>\n<h4>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u044b \u043b\u043e\u0433\u0438\u043d\u0430<\/h4>\n<p>\u0420\u0430\u0437 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u043a\u0430\u043a Vue \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Spring Security \u043d\u0430 \u043d\u0430\u0448\u0435 Vue \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0432\u044b\u043c \u0448\u0430\u0433\u043e\u043c \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c DSL \u043c\u0435\u0442\u043e\u0434 <code>formLogin()<\/code> \u0432 <code>SecurityConfig<\/code> \u0438 \u0432 <code>SocialConfigurer<\/code>. \u041f\u0440\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u0443\u043a\u0430\u0436\u0435\u043c <code>loginPage<\/code> \u0438 success\/failure Handlers. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 <code>SecurityConfig<\/code>. <code>successHandler<\/code> \u0438 <code>failureHandler<\/code> \u043f\u043e\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0435 \u0436\u0435, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043e\u043d\u0438 \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f.<\/p>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\">public class SecurityConfig {      public static final String LOGIN_PAGE = \"\/login\";     public static final String[] PERMIT_ALL_PATTERNS = {             LOGIN_PAGE,             \"\/static\/**\"     };      private final CustomOAuth2UserService customOAuth2UserService;     private final CustomUserDetailsService userDetailService;     private final PasswordEncoder passwordEncoder;     private final AuthenticationSuccessHandler successHandler = new SimpleUrlAuthenticationSuccessHandler();     private final AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         SocialConfigurer socialConfigurer = new SocialConfigurer()                 .oAuth2UserService(customOAuth2UserService)                 .successHandler(successHandler)                 .failureHandler(failureHandler)                 .formLogin(LOGIN_PAGE);         http.apply(socialConfigurer);          http.getSharedObject(AuthenticationManagerBuilder.class)                 .userDetailsService(userDetailService)                 .passwordEncoder(passwordEncoder);          http.authorizeHttpRequests(authorize ->                 authorize                         .requestMatchers(PERMIT_ALL_PATTERNS).permitAll()                         .anyRequest().authenticated()         );         return http.formLogin(configurer -> {             \/\/ \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430             configurer.loginPage(LOGIN_PAGE)                     .successHandler(successHandler)                     .failureHandler(failureHandler);         }).build();     } } <\/code><\/pre>\n<p>\u0412\u0442\u043e\u0440\u044b\u043c \u0448\u0430\u0433\u043e\u043c, \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c <code>UIController<\/code>. \u042d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 <code>\/login<\/code> \u0431\u044b\u043b\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0430 html \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0448\u0435\u0433\u043e frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p><code><strong>UIController.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Controller public class UIController {      @GetMapping(\"\/login\")     public String index() {         return \"index\";     } } <\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442, \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043b\u043e\u0433\u0438\u043d\u0430 \u043d\u0430\u0448\u0435 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c07\/c9e\/da9\/c07c9eda9cb569de5b1e84b1da94d0c2.png\" alt=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 vue \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \/login\" title=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 vue \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \/login\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c07\/c9e\/da9\/c07c9eda9cb569de5b1e84b1da94d0c2.png\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 vue \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \/login<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0441\u0432\u044f\u0437\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0444\u043e\u0440\u043c\u0443 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u0441\u043c\u0435\u043b\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043d\u043e\u0432\u043e\u0439 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0444\u043e\u0440\u043c\u044b \u043b\u043e\u0433\u0438\u043d\u0430. \u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0435\u0442\u0430\u043b\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 API <code>j-sso<\/code>.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f &#8212; <code>login-service.js<\/code><\/p>\n<p><code><strong>login-service.js<\/strong><\/code><\/p>\n<pre><code>import axios from 'axios';  export class LoginAPI {     __LOGIN_URL = \"\/login\";     __OAUTH_AUTHORIZATION_URL = \"\/oauth2\/authorization\/\";     __LOCATION_HEADER = process.env.VUE_APP_SSO_LOCATION_HEADER;      \/**      * \u0412\u0445\u043e\u0434 \u0447\u0435\u0440\u0435\u0434 \u043b\u043e\u0433\u0438\u043d\/\u043f\u0430\u0440\u043e\u043b\u044c.      * \u041f\u0440\u0438 \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\u0443\u0447\u0430\u0435\u0442 \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u0445 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439      * \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a {@see process.env.VUE_APP_SSO_LOCATION_HEADER} \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f URL \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430      * @param username - \u043b\u043e\u0433\u0438\u043d      * @param password - \u043f\u0430\u0440\u043e\u043b\u044c      *\/     login(username, password) {         let formData = new FormData();         formData.append(\"username\", username);         formData.append(\"password\", password);          return axios.post(this.__LOGIN_URL, formData).then(result => {             \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0435\u0441\u0442\u044c \u043b\u0438 \u0441\u043f\u0435\u0446. \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a             if (result.headers.has(this.__LOCATION_HEADER)) {                  \/\/ \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u0430\u0434\u0440\u0435\u0441                 window.location = result.headers.get(this.__LOCATION_HEADER);             }         });     }      \/**      * \u041c\u0435\u0442\u043e\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Yandex, Github \u0438\u043b\u0438 Google      * @param providerName - \u043e\u0434\u043d\u043e \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439: google, github, yandex      *\/     loginWith(providerName) {         window.location = this.__getOAuthAuthorizationUrl(providerName);     }      __getOAuthAuthorizationUrl(providerName) {         return this.__OAUTH_AUTHORIZATION_URL + providerName;     } }   export default new LoginAPI(); <\/code><\/pre>\n<p>\u0412\u0440\u043e\u0434\u0435 \u0431\u044b \u0432\u0441\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u044e\u0430\u043d\u0441. \u041e\u043d \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\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 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f. \u041f\u0440\u0438 \u0447\u0435\u043c, \u043e\u043d \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043d\u043e \u0438 backend \u0442\u043e\u0436\u0435. \u041d\u044e\u0430\u043d\u0441 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e <code>axios<\/code>, \u0432 \u0441\u0438\u043b\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>XMLHttpRequest<\/code>, \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u044b (\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>maxRedirects<\/code> &#8212; \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 <strong>node.js<\/strong>). \u0410 \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u043c\u043d\u0438\u043c, Spring Security \u0432 <code>j-sso<\/code> \u043f\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441 \u043d\u0430 \u043a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c, \u0432 \u0441\u0438\u043b\u0443 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 <code>Social Login<\/code>, \u0434\u0430\u043d\u043d\u043e\u0435 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u0430\u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c \u043a\u0443\u0447\u0443 &#171;\u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u043e\u0432&#187;, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u0421\u043c\u044b\u0441\u043b \u0435\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 \u0444\u043e\u0440\u043c\u0443 \u043c\u044b \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0430 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0410 URL \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a HTTP \u043e\u0442\u0432\u0435\u0442\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 Spring Security \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <code>AuthenticationSuccessHandler<\/code>, \u0447\u0442\u043e \u044f \u0438 \u0441\u0434\u0435\u043b\u0430\u043b.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 <code>SecurityConfig<\/code> \u0438 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a <code>CustomAuthenticationSuccessHandler<\/code>.<\/p>\n<p><code><strong>SecurityConfig.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @EnableWebSecurity @EnableMethodSecurity @RequiredArgsConstructor @Configuration(proxyBeanMethods = false) public class SecurityConfig {      public static final String LOGIN_PAGE = \"\/login\";     public static final String[] PERMIT_ALL_PATTERNS = {             LOGIN_PAGE,             \"\/static\/**\"     };      private final CustomOAuth2UserService customOAuth2UserService;     private final CustomUserDetailsService userDetailService;     private final PasswordEncoder passwordEncoder;     private final AuthorizationServerProperties authorizationServerProperties;      \/\/ handlers     private AuthenticationSuccessHandler oAuth2successHandler;     private AuthenticationSuccessHandler loginRequestSuccessHandler;     private AuthenticationFailureHandler failureHandler;      @Bean     public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {         SocialConfigurer socialConfigurer = new SocialConfigurer()                 .oAuth2UserService(customOAuth2UserService)                 .successHandler(oAuth2successHandler)                 .failureHandler(failureHandler)                 .formLogin(LOGIN_PAGE);         http.apply(socialConfigurer);         http.csrf(AbstractHttpConfigurer::disable);          http.getSharedObject(AuthenticationManagerBuilder.class)                 .userDetailsService(userDetailService)                 .passwordEncoder(passwordEncoder);          http.authorizeHttpRequests(authorize ->                 authorize                         .requestMatchers(PERMIT_ALL_PATTERNS).permitAll()                         .anyRequest().authenticated()         );         return http.formLogin(configurer -> {             configurer.loginPage(LOGIN_PAGE)                     .loginProcessingUrl(LOGIN_PAGE)                     .successHandler(loginRequestSuccessHandler)                     .failureHandler(failureHandler);         }).build();     }      @PostConstruct     private void initializeHandlers() {         \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 AuthenticationSuccessHandler \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u043b\u043e\u0433\u0438\u043d\u0430         this.loginRequestSuccessHandler = new CustomAuthenticationSuccessHandler(                 authorizationServerProperties.getAuthenticationSuccessUrl(),                 authorizationServerProperties.getCustomHandlerHeaderName()         );          \/\/ \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 AuthenticationSuccessHandler \u0434\u043b\u044f OAuth2 Client         this.oAuth2successHandler = new SimpleUrlAuthenticationSuccessHandler(                 authorizationServerProperties.getAuthenticationSuccessUrl()         );         this.failureHandler = new SimpleUrlAuthenticationFailureHandler();     } } <\/code><\/pre>\n<p><code><strong>CustomAuthenticationSuccessHandler.java<\/strong><\/code><\/p>\n<pre><code class=\"java\"> @Slf4j @RequiredArgsConstructor public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {      private final String locationUrl;     private final String headerName;      @Override     public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {         log.info(\"Authentication success\");         response.setHeader(headerName, locationUrl);     } } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 <code>j-sso<\/code>, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/1fb\/0c3\/f67\/1fb0c3f67cfe7585d7574ecc7719d2c2.png\" alt=\"\u041d\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 j-sso\" title=\"\u041d\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 j-sso\" width=\"1200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/1fb\/0c3\/f67\/1fb0c3f67cfe7585d7574ecc7719d2c2.png\"\/><\/p>\n<div><figcaption>\u041d\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 j-sso<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435, \u043d\u0430\u043c\u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435, \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f, \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438.<\/p>\n<blockquote>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/github.com\/dlabs71\/spring-authorization-server-example\/tree\/chapter-3.3\" 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, \u043c\u044b \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0438 \u0432 \u043f\u043b\u043e\u0442\u043d\u0443\u044e \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439. \u041c\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u0432\u0441\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0438\u0436\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0438\u043c \u0438\u0445 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438:<\/p>\n<ul>\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>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 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<\/ul>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f <code>j-sso<\/code>. \u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0435\u0433\u043e \u0441\u0442\u0435\u043a\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a. \u0418 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439:<\/p>\n<ul>\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>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 &#171;\u0417\u0430\u0431\u044b\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c&#187; (\u044d\u0442\u043e \u043d\u043e\u0432\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435)<\/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<\/ul>\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>Redis image. <a href=\"https:\/\/hub.docker.com\/_\/redis\/tags\" rel=\"noopener noreferrer nofollow\">Docker Hub<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/docs.spring.io\/spring-data\/data-redis\/docs\/current\/reference\/html\/\" rel=\"noopener noreferrer nofollow\">Spring Data Redis<\/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-session\/reference\/guides\/boot-redis.html\" rel=\"noopener noreferrer nofollow\">Spring Session<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/3.0.7\/reference\/htmlsingle\/#application-properties.web.spring.session.redis.cleanup-cron\" rel=\"noopener noreferrer nofollow\">\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Spring Session<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/3.0.7\/reference\/htmlsingle\/#application-properties.data.spring.data.redis.client-name\" rel=\"noopener noreferrer nofollow\">\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Spring Data Redis<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/spec.openapis.org\/oas\/latest.html\" rel=\"noopener noreferrer nofollow\">OpenAPI Specification<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/springdoc.org\/\" rel=\"noopener noreferrer nofollow\">Springdoc<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/swagger.io\/docs\/specification\/about\/\" rel=\"noopener noreferrer nofollow\">Swagger OpenAPI<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/spring.io\/guides\/gs\/serving-web-content\/\" rel=\"noopener noreferrer nofollow\">Spring MVC (Serving Web Content with Spring MVC)<\/a><\/p>\n<\/li>\n<li>\n<p>Tutorial <a href=\"https:\/\/www.tutorialspoint.com\/spring_boot\/spring_boot_thymeleaf.htm\" rel=\"noopener noreferrer nofollow\">Spring Boot &#8212; Thymeleaf<\/a><\/p>\n<\/li>\n<li>\n<p>Tutorial <a href=\"https:\/\/spring.io\/blog\/2013\/12\/19\/serving-static-web-content-with-spring-boot\" rel=\"noopener noreferrer nofollow\">\u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 Spring Boot<\/a><\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439\/\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/github.com\/eirslett\/frontend-maven-plugin\" rel=\"noopener noreferrer nofollow\">frontend-maven-plugin<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/maven.apache.org\/plugins\/maven-resources-plugin\/\" rel=\"noopener noreferrer nofollow\">maven-resources-plugin<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/cli.vuejs.org\/guide\/creating-a-project.html\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Vue Cli<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/cli.vuejs.org\/ru\/config\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Vue Cli<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/webpack.js.org\/api\/\" rel=\"noopener noreferrer nofollow\">Webpack<\/a><\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/748584\/\"> https:\/\/habr.com\/ru\/articles\/748584\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0430\u0442\u0435\u0439 \u044d\u0442\u043e\u0439 \u0441\u0435\u0440\u0438\u0438<\/h3>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/737548\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 1: \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<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/746698\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 2: \u0421\u0442\u0440\u043e\u0438\u043c \u0441\u0432\u043e\u0439 SSO. PostgreSQL \u0438 \u0440\u043e\u043b\u0435\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c<\/a><\/p>\n<\/li>\n<li>\n<p>\u0427\u0430\u0441\u0442\u044c 3: \u0421\u0442\u0440\u043e\u0438\u043c \u0441\u0432\u043e\u0439 SSO. \u0427\u0430\u0441\u0442\u044c 3: Redis, Swagger, Vue.js<\/p>\n<\/li>\n<\/ul>\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 SSO Server. \u0412 <a href=\"https:\/\/habr.com\/ru\/articles\/746698\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 Resource Server \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e SSO.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0421\u0423\u0411\u0414 PostgreSQL \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0440\u0430\u0441\u043a\u0430\u0442\u0430 \u0441\u0445\u0435\u043c\u044b \u0411\u0414.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446 \u0411\u0414 \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e \u043a\u043e\u0434\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0442\u0440\u0438 \u0442\u0438\u043f\u0430 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0435\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u0440\u043e\u043b\u0438 \u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438, \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 Spring Security.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0437 \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e (\u0441\u043c. \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 <a href=\"https:\/\/habr.com\/ru\/articles\/746698\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>) \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c Redis<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Swagger<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f <code>j-sso<\/code> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>Vue.js<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u044d\u0442\u0438 \u0442\u0440\u0438 \u043f\u0443\u043d\u043a\u0442\u0430. \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c!<\/p>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 3.1: \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c Redis<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0440\u0430\u0437\u0431\u043e\u0440\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0442\u043e\u043c, \u0437\u0430\u0447\u0435\u043c \u043c\u044b \u0432\u043e\u043e\u0431\u0449\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 Redis-\u0430 \u043a\u0430\u043a \u043a\u044d\u0448 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0442\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u044d\u0448\u0430. \u041d\u043e \u0437\u0430\u0447\u0435\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u044d\u0442\u043e\u0442 \u043a\u044d\u0448 \u0432 Redis-\u0435 \u0438 \u0447\u0442\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0442\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f? \u0414\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0441\u0442\u043e\u0438\u0442 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u0442\u0440\u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c &#8212; \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e (\u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438) \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043d\u0435\u0431\u043b\u0430\u0433\u043e\u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0445 \u043e\u0431\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430\u0445 (\u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u0445 \u0438\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0445 \u0441\u0431\u043e\u0435\u0432 \u043b\u0438\u0431\u043e \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).<\/p>\n<\/li>\n<li>\n<p>\u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c &#8212; \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0445 \u043f\u0440\u0438 \u0440\u043e\u0441\u0442\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u0440\u043e\u0431\u043b\u0435\u043c (\u043e\u0431\u044a\u0435\u043c\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u0438\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438).<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f &#8212; \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0443 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043b\u044e\u0434\u0435\u0439 (\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0438 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u044e\u0449\u0435\u043c\u0443 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u0443, \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c\u0441\u044f \u043a\u0430\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u0430\u043a \u0438 \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043a \u043d\u043e\u0432\u044b\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f).<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u043a \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u043c \u0441\u0431\u043e\u044f\u043c. \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0444\u0430\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0431\u043e\u0438 \u0432\u0438\u043d\u0447\u0435\u0441\u0442\u0435\u0440\u043e\u0432, \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u0444\u0435\u043a\u0442\u043e\u0432 \u041e\u0417\u0423, \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043f\u0438\u0442\u0430\u043d\u0438\u044f, \u0432\u044b\u0445\u043e\u0434 \u0438\u0437 \u0441\u0442\u0440\u043e\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043a\u0438, \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a\u0435\u043c-\u0442\u043e \u043d\u0435 \u0442\u043e\u0433\u043e \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u043a\u0430\u0431\u0435\u043b\u044f \u0438 \u0442.\u0434. \u0410 \u0432 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0432\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c, \u043a\u0430\u043a \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u0440\u0438 \u0432\u043e\u0437\u0440\u043e\u0441\u0448\u0435\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0435. \u0414\u043b\u044f \u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448 <code>j-sso<\/code> \u0432 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0432 \u0434\u0432\u0443\u0445, \u0430 \u0442\u043e \u0438 \u0431\u043e\u043b\u0435\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u0445 (\u0441\u043c. \u0441\u0445\u0435\u043c\u0443 \u043d\u0438\u0436\u0435).<\/p>\n<figure class=\"\">\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b j-sso<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u044d\u0442\u043e \u043f\u043e\u043d\u044f\u043b\u0438, \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e <code>j-sso<\/code>, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e Spring Security \u0438 \u0438\u0436\u0438 \u0441 \u043d\u0438\u043c\u0438, \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f \u0445\u0440\u0430\u043d\u0438\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438 \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 <code>j-sso<\/code>, \u0442\u043e \u043d\u0430 \u043a\u0430\u043a\u043e\u043c \u0438\u0437 \u043d\u0438\u0445 \u0431\u0443\u0434\u0443 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438? \u0418 \u0432\u043e \u0432\u0442\u043e\u0440\u044b\u0445, \u043d\u0430 \u043a\u0430\u043a\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043c\u044b \u043f\u043e\u043f\u0430\u0434\u0435\u043c \u043f\u043e\u0441\u043b\u0435 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438?<\/p>\n<p>\u0412\u0441\u0435 \u043f\u0430\u0440\u0438\u043b\u044c\u043d\u043e, \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 &#171;\u0440\u0430\u0437\u043c\u0430\u0437\u0430\u043d\u044b&#187; \u043f\u043e \u0432\u0441\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c, \u0430 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430 \u043a\u0430\u043a\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u043e\u043f\u0430\u0434\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043a\u0430\u043a\u043e\u0435-\u043d\u0438\u0431\u0443\u0434\u044c In Memory Data Grid \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 Redis. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 IMDG \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u044f \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e, \u0430 Spring \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435\u043e\u0431\u044a\u0435\u043c\u043b\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Redis, \u0442\u043e \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0435\u0433\u043e.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0436\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u044d\u0442\u043e\u0442 Redis \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043c Spring Security \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0430\u0448 <code>docker-compose.yml<\/code> \u0444\u0430\u0439\u043b \u0441\u0435\u0440\u0432\u0438\u0441 <code>j-redis<\/code>, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0441 \u0447\u0435\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p><code><strong>docker-compose.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\"> version: '3.3' services:   \/\/ .....    j-redis:     image: redis:7.2-rc2     restart: always     command: redis-server --save 20 1 --loglevel warning --requirepass qwerty12345678     ports:       - '6379:6379'     networks:       - j-network    \/\/ ..... <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.spring.io\/spring-data\/data-redis\/docs\/current\/reference\/html\/\" rel=\"noopener noreferrer nofollow\"><code>spring-boot-starter-data-redis<\/code><\/a> &#8212; \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f <code>j-sso<\/code> \u043a Redis.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.spring.io\/spring-session\/reference\/guides\/boot-redis.html\" rel=\"noopener noreferrer nofollow\"><code>spring-session-data-redis<\/code><\/a> &#8212; \u043d\u0443\u0436\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 Spring Session \u0432 Redis<\/p>\n<\/li>\n<\/ul>\n<p><code><strong>j-sso\/pom.xml<\/strong><\/code><\/p>\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;project xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"          xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"          xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">      \/\/ .....     &lt;dependencies>         &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-starter-data-redis&lt;\/artifactId>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.springframework.session&lt;\/groupId>             &lt;artifactId>spring-session-data-redis&lt;\/artifactId>         &lt;\/dependency>     &lt;\/dependencies>     \/\/ .....  &lt;\/project> <\/code><\/pre>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432 \u043d\u0430\u0448 <code>application.yml<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c:<\/p>\n<p><code><strong>application.yml<\/strong><\/code><\/p>\n<pre><code class=\"yaml\">spring:   application:     name: j-sso   session:     timeout: 1800                 # \u0412\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u0441\u0435\u0441\u0441\u0438\u0438 (\u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445)     redis:       flush-mode: on_save         # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u043e\u0433\u0434\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0430\u043d\u0441\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 (immediate \u0438\u043b\u0438 on_save)       namespace: j-sso:session    # \u041f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438\u043c\u0435\u043d \u0434\u043b\u044f \u043a\u043b\u044e\u0447\u0435\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0439.       save-mode: on_set_attribute # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0432 \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 (on_set_attribute, on_get_attribute, always)   data:     redis:                          # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a Redis       client-type: lettuce        # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0438\u043f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Redis (jedis \u0438\u043b\u0438 lettuce)       database: 0                 # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u043e\u043c\u0435\u0440 \u0411\u0414 Redis       host: localhost             # \u0425\u043e\u0441\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f       port: 6379                  # \u041f\u043e\u0440\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f       password: qwerty12345678    # \u041f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f       lettuce:                      # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043f\u0443\u043b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 lettuce         pool:           max-active: 16          # \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432 \u043f\u0443\u043b\u0435           max-idle: 8             # \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \"idle\" \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432 \u043f\u0443\u043b\u0435 <\/code><\/pre>\n<p>\u0412\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0435, \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b Spring Session \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/3.0.7\/reference\/htmlsingle\/#application-properties.web.spring.session.redis.cleanup-cron\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b Spring Data Redis \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/3.0.7\/reference\/htmlsingle\/#application-properties.data.spring.data.redis.client-name\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0441\u0443\u0434\u0438\u0442\u044c \u043f\u043e\u0447\u0435\u043c\u0443 <code>lettuce<\/code>, \u0430 \u043d\u0435 <code>jedis<\/code>. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (\u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 <code>spring-session-data-redis<\/code>). \u0410 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0435\u0442 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0432\u0435\u0441\u043e\u043c\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>lettuce<\/code>. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 <code>jedis<\/code> \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0433 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d, \u043a\u0430\u043a \u0438 <code>lettuce<\/code>.<\/p>\n<ul>\n<li>\n<p>Lettuce \u2014 \u044d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 Java-\u043a\u043b\u0438\u0435\u043d\u0442 Redis. \u041e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043a\u0430\u043a \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0443\u044e, \u0442\u0430\u043a \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c. \u0415\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p>Jedis \u2014 \u044d\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 Redis, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041e\u043d \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043d\u043e \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443, \u043a\u043b\u0438\u0435\u043d\u0442 <code>lettuce<\/code>, \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 \u0437\u0430 \u0441\u0447\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u041d\u043e \u043e\u043d \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0432 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u0441 Redis.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 (\u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>postgresql<\/code> \u0438 <code>redis<\/code>). \u0414\u0430\u043b\u0435\u0435, \u043f\u0440\u043e\u0439\u0434\u0435\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043b\u044e\u0431\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0438 \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 Redis.<\/p>\n<figure class=\"\">\n<div><figcaption>\u0414\u0430\u043d\u043d\u044b\u0435 \u0432 Redis \u043f\u043e\u0441\u043b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043f\u043e\u0434 \u043a\u043b\u044e\u0447\u043e\u043c \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0448\u0435\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 (\u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0443\u043a\u0438 <code>JSESSIONID<\/code>) \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0440\u044f\u0434 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u0440\u0435\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c Spring Security Context. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0448\u0438\u0445 \u0441\u0435\u0441\u0441\u0438\u0439 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 Redis. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 <code>j-sso<\/code>, \u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0438 \u0432\u0441\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438. \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e \u043f\u0440\u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0418\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u0447\u0430\u0441\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u044e\u0442 \u0441\u0432\u043e\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0438\u0449\u0443\u0442 \u0447\u0430\u0441\u0430\u043c\u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043a\u043e\u0434\u0435, \u0430 \u043d\u0430\u0434\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c Redis.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>j-sso<\/code> \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u0445 \u0438 \u043d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u0442\u044c\u0441\u044f \u043e \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430 \u0432\u0441\u0435\u0445 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b. \u041f\u043b\u044e\u0441\u043e\u043c \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u0432\u044b\u0448\u0435\u0441\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443, \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u0441\u0441\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 Redis \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e.<\/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.1\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b 3.2: \u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e Swagger<\/h3>\n<blockquote>\n<p>Swagger \u2014 \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 API \u043e\u0442 SmartBear Software \u0438 \u0431\u044b\u0432\u0448\u0430\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f OpenAPI.<\/p>\n<\/blockquote>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c:<\/p>\n<ol>\n<li>\n<p>OpenAPI 3 &#8212; \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0438 \u0438\u0445 endpoint-\u044b. <a href=\"https:\/\/spec.openapis.org\/oas\/latest.html\" rel=\"noopener noreferrer nofollow\">OpenAPI Specification<\/a><\/p>\n<\/li>\n<li>\n<p>Swagger UI &#8212; \u044d\u0442\u043e \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 OpenAPI. \u041e\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 endpoint-\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043d\u0430\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043b\u0435\u0433\u043a\u043e \u0438 \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u0442\u0435\u043b\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 API, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0435\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u041f\u041e.<\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f Swagger \u0432 Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0432\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438: Springfox \u0438 Springdoc. Springfox \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0435\u0440\u0435\u043c <a href=\"https:\/\/springdoc.org\/\" rel=\"noopener noreferrer nofollow\">Springdoc<\/a>.<\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043e\u0447\u0435\u043d\u044c \u0433\u0440\u0430\u043c\u043e\u0442\u043d\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430, \u043e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0441\u0432\u043e\u044e \u0447\u0430\u0441\u0442\u044c. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438\u0437 \u0438\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e <code>2.x.x<\/code>. \u0412\u0435\u0440\u0441\u0438\u044f <code>1.7.\u0445<\/code> \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e Spring Boot 3.<\/p>\n<figure class=\"\">\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 springdoc<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b, springdoc \u0438\u043c\u0435\u0435\u0442 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 Spring MVC, \u0442\u0430\u043a \u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0434\u043b\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 WebFlux. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0442\u0435 \u0447\u0442\u043e \u0441\u043f\u0440\u0430\u0432\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c WebFlux. \u0422\u0430\u043a\u0436\u0435, springdoc \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u043d\u0430 \u0442\u0435, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u0448\u0438\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432, \u043f\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OpenAPI. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u044d\u0442\u0438\u043c \u0435\u0449\u0451 \u0438 Swagger UI, \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432\u0441\u0435 \u0432 <code>j-sso<\/code>,<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-350373","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350373","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=350373"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350373\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=350373"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=350373"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=350373"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}