{"id":487275,"date":"2026-07-14T13:45:11","date_gmt":"2026-07-14T13:45:11","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=487275"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=487275","title":{"rendered":"Spring Security: \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 JWT \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u0445 \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e! \u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f, \u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 JWT \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438. \u0418 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043e\u0442\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435 \u043e\u0442 \u0442\u0435\u043c\u044b. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043c\u043e\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b\u043b\u043e\u0436\u0438\u043b\u0438 \u0432 \u043e\u0434\u0438\u043d \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c \u043a\u0430\u043d\u0430\u043b \u043f\u0440\u043e \u0431\u044d\u043a\u0435\u043d\u0434, \u0438 \u0432 \u043f\u043e\u0434\u043f\u0438\u0441\u0438 \u043a \u043c\u043e\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 RES, \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0447\u0442\u043e \u0442\u0430\u043c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u0435\u0441\u0441\u0438\u0439 \u0438 \u043a\u0443\u043a\u0438, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e jwt, \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e \u044f \u0431\u044b\u043b \u0443\u0434\u0438\u0432\u043b\u0451\u043d, \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u043d\u0435 \u043c\u043d\u043e\u0433\u043e \u0433\u0440\u0443\u0441\u0442\u043d\u043e\u0432\u0430\u0442\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u0437\u0430\u043f\u043e\u0441\u0442\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e, \u043e\u043d\u0438 \u0438\u0445 \u043d\u0435 \u0447\u0438\u0442\u0430\u044e\u0442, \u043d\u043e \u0434\u0430 \u043b\u0430\u0434\u043d\u043e, JWT \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u0433\u043e\u043d\u044f\u0435\u043c =)<\/p>\n<h2>\u0427\u0442\u043e \u0436\u0435 \u0442\u0430\u043a\u043e\u0435 \u044d\u0442\u043e \u043d\u0430\u0448\u0435 JWT \u0438 \u0441 \u0447\u0435\u043c \u0435\u0433\u043e \u0435\u0434\u044f\u0442?<\/h2>\n<p><strong>JWT (Json web token) &#8212; <\/strong>\u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 3\u0445 \u0447\u0430\u0441\u0442\u0435\u0439: 1 &#8212; header (\u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c), 2 &#8212; payload (\u0434\u0430\u043d\u044b\u043d\u0435) \u0438 3 &#8212; signatere(\u043f\u043e\u0434\u043f\u0438\u0441\u044c).<\/p>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043a\u0430 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c? \u0447\u0442\u043e \u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0435? \u0447\u0442\u043e \u0437\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u044c?<\/p>\n<ul>\n<li>\n<p><code>header<\/code> (\u0438\u043b\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c) &#8212; \u044d\u0442\u043e json \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 <code>Base64Url<\/code> (\u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Base64, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 url-\u0430\u0434\u0440\u0435\u0441\u0430\u0445 \u0438 \u0438\u043c\u0435\u043d\u0430\u0445 \u0444\u0430\u0439\u043b\u043e\u0432), \u043e\u043d \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>HS256<\/code> \u0438\u043b\u0438 <code>RS256<\/code>) \u0438 \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e jwt).<br \/>\u0415\u0441\u043b\u0438 \u0435\u0433\u043e \u0440\u0430\u0441\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c json \u0432 \u0432\u0438\u0434\u0435:<br \/>{<br \/>    &#171;alg&#187; : &#171;HS256&#187;,<br \/>    &#171;typ&#187; : &#171;JWT&#187;<br \/>}<br \/>\u041e\u043d \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u043a\u0430\u043a\u0438\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u044c.<\/p>\n<\/li>\n<li>\n<p><code>Payload<\/code> (\u0438\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435) &#8212; \u044d\u0442\u043e \u0442\u043e\u0436\u0435 json \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 Base64Url, \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f <code>claims<\/code> &#8212; \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u0441\u0435\u0441\u0441\u0438\u0438.<br \/>\u0415\u0441\u043b\u0438 \u043c\u044b \u0435\u0433\u043e \u0440\u0430\u0441\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0447\u0442\u043e-\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<br \/>{   <br \/>    &#171;sub&#187;: &#171;user1&#187;,   <br \/>    &#171;role&#187;: &#171;admin&#187;,   <br \/>    &#171;exp&#187;: 1752480000 <br \/>} <br \/>* \u041d\u043e \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e <code>payload<\/code> \u043d\u0435 \u0448\u0438\u0444\u0440\u0443\u0435\u0442\u0441\u044f, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f &#8212;  \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u0435\u0433\u043e \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443 Base64 \u0438 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435. <code>\u041f\u043e \u044d\u0442\u043e\u043c\u0443 \u0442\u0443\u0434\u0430 \u043d\u0435\u043b\u044c\u0437\u044f \u043a\u043b\u0430\u0441\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u0438 \u0438\/\u0438\u043b\u0438 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435!<\/code> <\/p>\n<\/li>\n<li>\n<p><code>Signature<\/code> (\u0438\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u044c) &#8212; \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u0448 \u0442\u043e\u043a\u0435\u043d \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u044b\u043c \u043e\u0442 \u043f\u043e\u0434\u0434\u0435\u043b\u043a\u0438. \u042d\u0442\u043e \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u0451\u043c \u0441\u043a\u043b\u0435\u0438\u0432\u0430\u043d\u0438\u044f <code>payload<\/code> \u0438 <code>header<\/code> \u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0447\u043a\u0443 \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u043d\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0440\u0432\u0435\u0440.<br \/>\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<br \/>HMACSHA256(   <br \/>   base64UrlEncode(header) + &#171;.&#187; + base64UrlEncode(payload),   secret_key<br \/>) <br \/><code>HMAC-SHA256<\/code> &#8212; \u044d\u0442\u043e \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0445\u044d\u0448-\u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>SHA-265<\/code> \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c. \u0418 \u043e\u043d \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445, \u0437\u0430\u0449\u0438\u0449\u0430\u044f \u043e\u0442 \u043f\u043e\u0434\u0434\u0435\u043b\u043a\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435 \u043f\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u0430\u043d\u0430\u043b\u0430\u043c.<\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0442\u043e\u043a\u0435\u043d: \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 <code>header<\/code> \u0438 <code>payload<\/code>, \u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442 \u0438\u0445, \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c &#8212; \u043f\u043e\u0434\u0443\u0447\u0430\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u044c. \u0417\u0430\u0442\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0443 (\u043e\u0431\u044b\u0447\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u043b\u043e\u0433\u0438\u043d\u0430). \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u043e\u043a\u0435\u043d \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 (\u043e\u0431\u044b\u0447\u043d\u043e \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 <code>Authorization: Bearer &lt;\u0442\u043e\u043a\u0435\u043d&gt;<\/code>). \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430\u043d\u043e\u0432\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u044c \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 header \u0438 payload \u0441 \u0442\u0435\u043c \u0436\u0435 \u0441\u0430\u043c\u044b\u043c \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b\u043b\u0430 \u0432 \u0442\u043e\u043a\u0435\u043d\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0448\u0451\u043b \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, JWT \u043d\u0435 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u043e \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0438\u0445 <strong>\u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u044c<\/strong> &#8212; \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/p>\n<\/li>\n<\/ul>\n<h2>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 session \u0438 jwt<\/h2>\n<p>\u041c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u043d\u0430\u0435\u043c \u0438 \u043e \u0441\u0435\u0441\u0441\u0438\u044f\u0445, \u0438 \u043e jwt. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0434\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u0445 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c.<br \/>1. \u0421\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 &#8212; \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0445\u043e\u0442\u044f \u0432 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f jwt \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435<br \/>2. \u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0442\u044f\u0436\u0435\u043b\u0435\u0435, \u043d\u0435\u0436\u0435\u043b\u0438 jwt, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0443\u0436\u0435\u043d \u043e\u0431\u0449\u0438\u0439 Redis<br \/>3. \u041d\u043e \u043e\u0442\u043e\u0437\u0432\u0430\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u044e \u0438 \u043a\u0443\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0434\u043b\u044f \u043e\u0442\u0437\u044b\u0432\u0430 jwt \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0430\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u043a \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043d \u0441\u0430\u043c \u0441\u0442\u0430\u043d\u0435\u0442 \u043d\u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c.<br \/>4. \u0421\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u044f\u0437\u0432\u0438\u043c\u044b \u043a CSRF \u0430\u0442\u0430\u043a\u0435, \u043d\u043e jwt \u043a \u043d\u0435\u0439 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435 \u0443\u044f\u0437\u0432\u0438\u043c.<br \/>5. \u0421\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u0438 MPA (Multi-Page Application), \u0430 jwt \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445 \u0438 SPA (Single Page Application)<\/p>\n<h2>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430, \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u0434 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0438\u0437 3\u0445 \u0441\u0442\u0440\u043e\u043a. \u0418 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 <code>application.properties<\/code>:<\/p>\n<pre><code class=\"java\">\/\/\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0434\u043b\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 HMAC-SHA256SecretKey key = Jwts.SIG.HS256.key().build();\/\/\u041f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 application.propertiesString base64 = Encoders.BASE64.encode(key.getEncoded());System.out.println(base64);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432 \u0441\u0430\u043c\u043e\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <code>@SpringBootApplication<\/code>. \u0412 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 <code>SecurityCourseApplication<\/code>.<br \/> \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u0434\u043e\u043a\u0435\u0440 \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d) \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043d\u0430\u043c \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/747\/6a7\/0cb\/7476a70cb5f00327d8c88206f41e54f4.png\" alt=\"\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430\" title=\"\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430\" width=\"843\" height=\"387\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/747\/6a7\/0cb\/7476a70cb5f00327d8c88206f41e54f4.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/747\/6a7\/0cb\/7476a70cb5f00327d8c88206f41e54f4.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u0441\u0430\u043c\u043e\u0439 \u043d\u0438\u0436\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 <code>application.properties<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043d\u043e\u0432\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a:<\/p>\n<pre><code>#\u0421\u0430\u043c \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447jwt-secret=fdLwz0v0J3UQDrb+DJl2+618BLj24xPq+ZZkU95uUsQ=#\u0412\u0440\u0435\u043c\u044f \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0440\u043e\u0447\u0435 jwt \u0442\u043e\u043a\u0435\u043d \u0438\u0441\u0442\u0435\u0447\u0451\u0442 (\u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445)jwt-expiration=3600000#\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u0440\u043e\u043a\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (\u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445)jwt-refresh-expiration=604800000<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0443 \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u043e\u0442 \u043a\u043e\u0434 \u0438\u0437 3\u0445 \u0441\u0442\u0440\u043e\u043a \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0438\u0437-\u0437\u0430 \u043d\u0435\u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a java-code \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432.<\/p>\n<h2>JwtService &#8212; \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432<\/h2>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 <code>sevice<\/code>, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 <code>JwtService<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433.<\/p>\n<pre><code class=\"java\">@Servicepublic class JwtService {    @Value(\"${jwt-secret}\")    private String secretKey;    @Value(\"${jwt-expiration}\")    private long jwtExpiration;    \/\/\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b    private SecretKey getSigningKey(){        \/\/\u041f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 SecretKey, \u043a\u043e\u0442\u043e\u0440\u044b\u043c        \/\/jjwt (java json web token) \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b        byte[] keyBytes = Decoders.BASE64.decode(secretKey);        \/\/\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043a\u043b\u044e\u0447 \u0434\u043b\u044f HMAC-SHA256 \u043f\u043e\u0434\u043f\u0438\u0441\u0438        return Keys.hmacShaKeyFor(keyBytes);    }    \/\/\u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0435\u0433\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u044c \u0438 \u0434\u043e\u0441\u0442\u0430\u0451\u0442 \u0438\u0437 \u043d\u0435\u0433\u043e \u0432\u0441\u0435 claims (payload)    \/\/\u0415\u0441\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u044c \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0438\u043b\u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0442\u043e\u043a\u0435\u043d\u0430 \u043d\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 - \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435    \/\/\u042d\u0422\u041e \u0415\u0414\u0418\u041d\u0421\u0422\u0412\u0415\u041d\u041d\u041e\u0415 \u041c\u0415\u0421\u0422\u041e \u0413\u0414\u0415 \u041f\u0420\u041e\u0418\u0421\u0425\u041e\u0414\u0418\u0422 \u041a\u0420\u0418\u041f\u0422\u041e\u0413\u0420\u0410\u0424\u0418\u0427\u0415\u0421\u041a\u0410\u042f \u041f\u0420\u041e\u0412\u0415\u0420\u041a\u0410 \u0422\u041e\u041a\u0415\u041d\u0410    private Claims extractAllClaims(String token){        return Jwts.parser()                .verifyWith(getSigningKey()) \/\/\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447                .build()                .parseSignedClaims(token) \/\/ !\u043f\u0430\u0440\u0441\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u044c!                .getPayload(); \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c payload    }    \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442: \u0438\u0441\u0442\u0451\u043a \u043b\u0438 \u0442\u043e\u043a\u0435\u043d    private boolean isTokenExpired(String token){        \/\/extractAllClaims(token).getExpiration() - \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 Date, \u0438\u0437\u0432\u043b\u0435\u0447\u0451\u043d\u043d\u044b\u0439 \u0438\u0437 claim'\u0430        \/\/ exp \u0442\u043e\u043a\u0435\u043d\u0430. (\u0412\u0440\u0435\u043c\u044f \u043a\u043e\u0433\u0434\u0430 \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0442\u0430\u0442\u044c \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c)        \/\/.before(new Date()) - \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true, \u0435\u0441\u043b\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c new Date()        \/\/ \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0449\u0435, \u0442\u043e - \u00ab\u0414\u0430\u0442\u0430 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0441\u0435\u0439\u0447\u0430\u0441?\u00bb \u0435\u0441\u043b\u0438 \u0434\u0430, \u0437\u043d\u0430\u0447\u0438\u0442 \u0441\u0440\u043e\u043a \u0443\u0436\u0435 \u043f\u0440\u043e\u0448\u0451\u043b, \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u043e\u0441\u0440\u043e\u0447\u0435\u043d.        return extractAllClaims(token).getExpiration().before(new Date());    }    \/\/\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b    \/\/\u0414\u043e\u0441\u0442\u0430\u0451\u0442 username \u0438\u0437 claim'\u0430 \u0442\u043e\u043a\u0435\u043d\u0430 (claim \"sub\" -&gt; subject)    \/\/\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0437\u0430 \u043a\u043e\u0433\u043e \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0443, \u0435\u0449\u0451 \u0434\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u043a\u0435\u043d\u0430.    public String extractUsername(String token){        return extractAllClaims(token).getSubject();    }    \/\/\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 jwt \u0442\u043e\u043a\u0435\u043d \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430    \/\/\u0412 payload \u043a\u043b\u0430\u0434\u0443\u0442\u0441\u044f: subject, \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f    \/\/\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u043e\u043b\u0435\u0439 - \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u0443 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0431\u0434.    \/\/\u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 extractClaims - \u0434\u043e\u043f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f payload    \/\/UserDetails - \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d    public String generateToken(Map&lt;String, Objects&gt; extractClaims, UserDetails userDetails){        return Jwts.builder()                \/\/\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 payload \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 claims                .claims(extractClaims)                \/\/\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 claim \"sub\" - \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f                .subject(userDetails.getUsername())                \/\/\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \"iat\" - \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430                .issuedAt(new Date())                \/\/\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \"exp\"- \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430                .expiration(new Date(System.currentTimeMillis() + jwtExpiration))                \/\/\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 claim \"roles\" \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043f\u0440\u0430\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f                .claim(\"roles\", userDetails.getAuthorities().stream()                        \/\/\u0414\u043e\u0441\u0442\u0430\u0451\u043c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u043e\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \"ROLE_USER\"                        .map(GrantedAuthority::getAuthority)                        \/\/\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0440\u043e\u043b\u0438 \u0432 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 List&lt;String&gt;                        .collect(Collectors.toList()))                \/\/\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c                .signWith(getSigningKey())                \/\/\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0451 \u0432 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443                .compact();    }    \/\/\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 jwt \u0442\u043e\u043a\u0435\u043d, \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 claims    \/\/\u041f\u043e \u0441\u0443\u0442\u0438 \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0432\u044b\u0448\u0435    public String generateToken(UserDetails userDetails){        return generateToken(new HashMap&lt;&gt;(), userDetails);    }    \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0438 \u0441\u0440\u043e\u043a \u043d\u0435 \u0438\u0441\u0442\u0451\u043a    public boolean isTokenValid(String token, UserDetails userDetails){        final String username = extractUsername(token); \/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c username \u0438\u0437 userDetails        \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0442\u043e\u043a\u0435\u043d \u043d\u0430 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u0440\u043e\u043a\u0430        return username.equals(userDetails.getUsername()) &amp;&amp; !isTokenExpired(token);    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u043d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c, \u0438 \u0432 \u0446\u0435\u043b\u043e\u043c \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u0436\u0435 \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0441\u043b\u043e\u0436\u043d\u043e)<\/p>\n<h2>JwtAuthenticationFilter<\/h2>\n<p><code>JwtAuthenticationFilter<\/code> \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 <code>JwtServise<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442. \u0424\u0438\u043b\u044c\u0442\u0440 \u0447\u0438\u0442\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 <code>Authorization: Bearer &lt;\u0442\u043e\u043a\u0435\u043d&gt;<\/code>, \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u0438 \u043a\u043b\u0430\u0434\u0451\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432 <code>SecurityContext<\/code>.<br \/>\u0422\u0435\u043f\u0435\u0440\u044c \u0432 \u043f\u0430\u043f\u043a\u0435 <code>config<\/code> \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u043a\u0435\u0442:  <code>filter<\/code> \u0438 \u0443\u0436\u0435 \u0432 \u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c JwtAuthenticationFilter.<\/p>\n<pre><code class=\"java\">@Component@RequiredArgsConstructorpublic class JwtAuthenticationFilter extends OncePerRequestFilter {    private final JwtService jwtService;    private final UserDetailsServiceImpl userDetailsService;    @Override    protected void doFilterInternal(HttpServletRequest request,                                    HttpServletResponse response,                                    FilterChain filterChain) throws ServletException, IOException{        \/\/\u0414\u043e\u0441\u0442\u0430\u0451\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a Authorization        final String authHeader = request.getHeader(\"Authorization\");        \/\/\u041f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435 \u0431\u0435\u0437 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438        if(authHeader == null || !authHeader.startsWith(\"Bearer \")){            filterChain.doFilter(request, response);            return;        }        final String jwt = authHeader.substring(7); \/\/ \u0443\u0431\u0438\u0440\u0430\u0435\u043c \"Bearer \"        try{            \/\/\u0414\u043e\u0441\u0442\u0430\u0451\u043c username \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430            final String username = jwtService.extractUsername(jwt);            \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0435\u0449\u0451 \u043d\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d            if(username != null &amp;&amp; SecurityContextHolder.getContext().getAuthentication() == null){                \/\/\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u0431\u0434                UserDetails userDetails = userDetailsService.loadUserByUsername(username);                \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0441\u0442\u044c (\u043f\u043e\u0434\u043f\u0438\u0441\u044c, \u0441\u0440\u043e\u043a, \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u044e\u0437\u0435\u0440\u0430)                if(jwtService.isTokenValid(jwt, userDetails)){                    \/\/\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f Spring Security                    UsernamePasswordAuthenticationToken authToken =                            new UsernamePasswordAuthenticationToken(                                    userDetails,                                    null,                                    userDetails.getAuthorities()                            );                    \/\/\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0434\u0435\u0442\u0430\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e \u0442\u0438\u043f\u0443 (IP, session id, \u0438 \u0442\u0434)                    authToken.setDetails(                            new WebAuthenticationDetailsSource().buildDetails(request)                    );                    \/\/\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442                    SecurityContextHolder.getContext().setAuthentication(authToken);                }            }        } catch (JwtException e){            \/\/\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d - \u043d\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d            \/\/ ExceptionTranslationFilter \u0432\u0435\u0440\u043d\u0451\u0442 401 \u0435\u0441\u043b\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0437\u0430\u0449\u0438\u0449\u0451\u043d            System.out.println(\"\u0422\u043e\u043a\u0435\u043d \u043d\u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439, \u043e\u0448\u0438\u0431\u043a\u0430: \" + e.getMessage());        }        \/\/\u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435        filterChain.doFilter(request, response);    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 <code>OncePerRequestFilter<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438\u0437 Spring, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0437\u0430 \u0437\u0430\u043f\u0440\u043e\u0441, \u0447\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u043c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 Spring Security.<br \/>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043b\u044f \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 jwt, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0448 <code>SecurityConfig<\/code>, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u0435\u0442\u043e\u0434 <code>filterChain<\/code>:<\/p>\n<pre><code class=\"java\">@Configuration@EnableWebSecurity@RequiredArgsConstructorpublic class SecurityConfig {    private final UserDetailsServiceImpl userDetailsService;    private final PasswordEncoder passwordEncoder;    private final JwtAuthenticationFilter jwtAuthenticationFilter;    @Bean    public AuthenticationProvider authenticationProvider(){        DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);        provider.setPasswordEncoder(passwordEncoder);        return provider;    }    @Bean    public AuthenticationManager authenticationManager(AuthenticationConfiguration config){        return config.getAuthenticationManager();    }    @Bean    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{        http.csrf(                \/\/\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0449\u0438\u0442\u044b \u043e\u0442 csrf \u0430\u0442\u0430\u043a\u0438 (\u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c)                csrf -&gt; csrf.disable())                .authorizeHttpRequests(auth -&gt;                        auth.requestMatchers(\"\/api\/auth\/**\").permitAll()                                .requestMatchers(\"\/api\/admin\").hasRole(\"ADMIN\")                                .anyRequest().authenticated())                \/\/\u0411\u0435\u0437 \u0441\u0435\u0441\u0441\u0438\u0439 \u043a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u0442\u043e\u043a\u0435\u043d\u0443                .sessionManagement(session -&gt;                        session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))                .authenticationProvider(authenticationProvider())                \/\/\u041d\u0430\u0448 \u0444\u0438\u043b\u044c\u0442\u0440 \u0432\u0441\u0442\u0430\u0451\u0442 \u043f\u0435\u0440\u0435\u0434 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c \u043b\u043e\u0433\u0438\u043d\u0430                .addFilterBefore(                        jwtAuthenticationFilter,                        UsernamePasswordAuthenticationFilter.class                );        return http.build();    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0438 \u043b\u043e\u0433\u0438\u043d\u043e\u043c. \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u0443 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. \u0418 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043c\u0430\u043b\u043e\u0441\u0442\u044c \u0443\u0442\u043e\u0447\u043d\u0438\u0442\u044c, \u0447\u0442\u043e ProblemDetails &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u0432 <code>@RestControllerAdvice<\/code>, \u0430 \u043d\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0415\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c HTTP-\u043e\u0442\u0432\u0435\u0442\u044b, \u0442\u043e \u044d\u0442\u043e \u043d\u0430\u0440\u0443\u0448\u0438\u0442 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0438\u0437 <code>SOLID<\/code>. \u0422\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u0443 \u0441\u0432\u043e\u0438\u0445 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 <code>util<\/code>.<\/p>\n<pre><code class=\"java\">public record RegisterRequest(String username, String password) {}public record AuthResponse(String accessToken) {}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>ProblemDetail<\/code> \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 <code>@RestControllerAdvice<\/code>:<\/p>\n<pre><code class=\"java\">public class UsernameTakenException extends ErrorResponseException {    private static ProblemDetail asProblem(String username){        ProblemDetail problemDetail = ProblemDetail.forStatus(HttpStatus.CONFLICT);        problemDetail.setTitle(\"Username taken\");        problemDetail.setDetail(\"\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441 \u0438\u043c\u0435\u043d\u0435\u043c: '%s' \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442\".formatted(username));        problemDetail.setProperty(\"username\", username);        return problemDetail;    }    public UsernameTakenException(String username){        super(HttpStatus.CONFLICT, asProblem(username), null);    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0443 \u0438 \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u043c, \u044f \u043d\u0430\u0441 \u0432\u0441\u0435\u0445 \u043f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u044e!<\/p>\n<h2>AuhtService \u0438 AuthController<\/h2>\n<pre><code class=\"java\">@Service@RequiredArgsConstructorpublic class AuthService {    private final UserRepository userRepository;    private final PasswordEncoder passwordEncoder;    private final JwtService jwtService;    private final AuthenticationManager authenticationManager;    \/\/\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f    public AuthResponse register(RegisterRequest request){        \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0435\u0433\u043e username        if(userRepository.existsByUsername(request.username())){            throw new UsernameTakenException(request.username());        }        \/\/\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f        User user = new User();        user.setUsername(request.username());        user.setPassword(passwordEncoder.encode(request.password()));        user.setRoles(Set.of(Role.USER));        \/\/\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0431\u0434        userRepository.save(user);        \/\/\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c DTO \u0441 accessToken'\u043e\u043c \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f        return new AuthResponse(jwtService.generateToken(user));    }    \/\/\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f    public AuthResponse login(LoginRequest request){        \/\/\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0438 \u043f\u0430\u0440\u043e\u043b\u044e \u0438 \u0432\u044b\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u044b\u0439 JWT.        \/\/\u0414\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0441\u0430\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u0430\u0440\u043e\u043b\u044f AuthenticationManager \u2014 \u0442\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c        \/\/\u0442\u0443 \u0436\u0435 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 (DaoAuthenticationProvider + PasswordEncoder), \u0447\u0442\u043e \u0438 \u0444\u043e\u0440\u043c\u044b \u043b\u043e\u0433\u0438\u043d\u0430.        \/\/\u0412\u044b\u0431\u0440\u043e\u0441\u0438\u0442 BadCredentialsException \u0435\u0441\u043b\u0438 \u043b\u043e\u0433\u0438\u043d\/\u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435\u0432\u0435\u0440\u043d\u044b        authenticationManager.authenticate(                new UsernamePasswordAuthenticationToken(                        request.username(),                        request.password()                )        );        \/\/\u041f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d        \/\/\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e        \/\/ \u043d\u0443 \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043a\u0438\u043d\u0435\u0442 throw new NoSuchElementException(\"No value present); \u043f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443        User user = userRepository.findByUsername(request.username()).orElseThrow();        \/\/\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c DTO \u0441 accessToken'\u043e\u043c \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f        return new AuthResponse(jwtService.generateToken(user));    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u0446\u0435\u043b\u043e\u043c \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043f\u043e \u043a\u043e\u0434\u0443 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u043e \u0432\u0441\u0451  \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0438 \u0447\u0442\u043e \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442. \u0414\u0443\u043c\u0430\u044e \u043c\u043e\u0436\u0435\u043c \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a <code>AuthController<\/code> =) \u041d\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043d\u0430\u0448 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 <code>SessionAuthController<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u0443\u0442 \u043c\u044b \u043f\u0435\u0440\u0435\u0448\u043b\u0438 \u043d\u0430 JWT \u0438 \u0441\u0435\u0441\u0441\u0438\u0438 \u043d\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u044b \u0438 \u0443 \u043d\u0430\u0441 \u0434\u043b\u044f \u043d\u0438\u0445 \u043d\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a. <\/p>\n<pre><code class=\"java\">@RestController@RequestMapping(\"\/api\/auth\")@RequiredArgsConstructorpublic class AuthController {    private final AuthService authService;        @PostMapping(\"\/register\")    public ResponseEntity&lt;AuthResponse&gt; register(@RequestBody RegisterRequest request){        return ResponseEntity.ok(authService.register(request));    }        @PostMapping(\"\/login\")    public ResponseEntity&lt;AuthResponse&gt; login (@RequestBody LoginRequest request){        return ResponseEntity.ok(authService.login(request));    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e! \u041d\u0438\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/016\/8a9\/67a\/0168a967acecdf35b7935b922c6005a1.png\" alt=\"\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\" title=\"\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\" width=\"781\" height=\"654\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/016\/8a9\/67a\/0168a967acecdf35b7935b922c6005a1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/016\/8a9\/67a\/0168a967acecdf35b7935b922c6005a1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4e5\/2c7\/553\/4e52c755359bb6f98e7eda7841c23998.png\" alt=\"\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\" title=\"\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\" width=\"769\" height=\"646\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4e5\/2c7\/553\/4e52c755359bb6f98e7eda7841c23998.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4e5\/2c7\/553\/4e52c755359bb6f98e7eda7841c23998.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u044b \u0443\u0432\u0438\u0434\u0435\u043b\u0438 \u0447\u0442\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0434 200 \u0438 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 accessToken. \u041d\u043e \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0435\u0441\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u043c\u0430\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e?<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/219\/604\/703\/21960470360515752ee662ae8cf413c5.png\" alt=\"\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0437\u0430\u0439\u0442\u0438 \u043d\u0430 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0441 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0440\u043e\u043b\u0435\u043c\" title=\"\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0437\u0430\u0439\u0442\u0438 \u043d\u0430 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0441 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0440\u043e\u043b\u0435\u043c\" width=\"777\" height=\"612\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/219\/604\/703\/21960470360515752ee662ae8cf413c5.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/219\/604\/703\/21960470360515752ee662ae8cf413c5.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0437\u0430\u0439\u0442\u0438 \u043d\u0430 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0441 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0440\u043e\u043b\u0435\u043c<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u043c\u044b \u0443\u0432\u0438\u0434\u0435\u043b\u0438 \u0432\u044b\u0448\u0435, \u043d\u0430\u043c \u0432\u0435\u0440\u043d\u0443\u043b\u0441\u044f \u043a\u043e\u0434 403, \u0438 \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0435\u0449\u0451 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u041d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0443\u0436\u0435 \u0441 \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0441\u044f username, \u0438 \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e47\/52f\/7e2\/e4752f7e2f5755c7b419dc85d8cfdeb3.png\" alt=\"\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0441 \u0437\u0430\u043d\u044f\u0442\u044b\u043c username\" title=\"\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0441 \u0437\u0430\u043d\u044f\u0442\u044b\u043c username\" width=\"776\" height=\"651\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e47\/52f\/7e2\/e4752f7e2f5755c7b419dc85d8cfdeb3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e47\/52f\/7e2\/e4752f7e2f5755c7b419dc85d8cfdeb3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0441 \u0437\u0430\u043d\u044f\u0442\u044b\u043c username<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u043d\u0430\u043c \u0432\u0435\u0440\u043d\u0443\u043b\u0441\u044f \u043a\u043e\u0434 403 \u0432\u043c\u0435\u0441\u0442\u043e 409. \u041d\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043b\u043e\u0433\u0438, \u0442\u043e \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0448\u0438\u0431\u043a\u0430 409<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3e9\/a81\/9ee\/3e9a819ee388140964ec0a5fe1e75622.png\" alt=\"\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430\" title=\"\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430\" width=\"1709\" height=\"53\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/3e9\/a81\/9ee\/3e9a819ee388140964ec0a5fe1e75622.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3e9\/a81\/9ee\/3e9a819ee388140964ec0a5fe1e75622.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441, \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442? \u0418 \u043e\u0442\u0432\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439. Spring \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0430\u0442\u044c 409, \u043d\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <code>\/error<\/code>. \u042d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0442\u043e\u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u043e\u0439 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 &#8212; \u0430 \u044d\u0442\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0430. \u0412 \u0438\u0442\u043e\u0433\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 403 \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0433\u043e 409.  <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/abf\/fba\/62a\/abffba62aa988347e6dfa1e0e0d8eb94.png\" alt=\"\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b\" title=\"\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b\" width=\"1881\" height=\"901\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/abf\/fba\/62a\/abffba62aa988347e6dfa1e0e0d8eb94.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/abf\/fba\/62a\/abffba62aa988347e6dfa1e0e0d8eb94.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u0432\u044b\u0448\u0435 \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>.requestMatchers(\"\/error\").permitAll()<\/code> \u0447\u0442\u043e\u0431\u044b Sptring \u043c\u043e\u0433 \u0431\u0435\u0441\u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430 url: <code>\/error<\/code>.<\/p>\n<p>\u0414\u0443\u043c\u0430\u044e \u043d\u0430 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e. \u0418 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u043f\u043b\u0430\u043d\u0430\u0445. \u041f\u0430\u0440\u043e\u0447\u043a\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0435\u043c\u044b \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f \u043f\u043e \u0433\u043b\u0443\u0431\u0436\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 RefreshToken, \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u041c\u0435\u0442\u043e\u0434-\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0438 \u0442.\u0434. \u0422\u0430\u043a \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u0442\u0435\u043c\u0443 JWT. <br \/>\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0440\u0430\u0437 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043a\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u044e, \u0438 \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0434\u043b\u044f \u0432\u0430\u0441. \u041a\u0440\u0438\u0442\u0438\u043a\u0430 \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442\u0441\u044f \u0438 \u0431\u0443\u0434\u0435\u0442 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c =)<\/p>\n<\/div>\n<p>\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\/1059086\/\">https:\/\/habr.com\/ru\/articles\/1059086\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u0445 \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e! \u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f, \u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 JWT \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438. \u0418 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043e\u0442\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435 \u043e\u0442 \u0442\u0435\u043c\u044b. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043c\u043e\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b\u043b\u043e\u0436\u0438\u043b\u0438 \u0432 \u043e\u0434\u0438\u043d \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c \u043a\u0430\u043d\u0430\u043b \u043f\u0440\u043e \u0431\u044d\u043a\u0435\u043d\u0434, \u0438 \u0432 \u043f\u043e\u0434\u043f\u0438\u0441\u0438 \u043a \u043c\u043e\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 RES, \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0447\u0442\u043e \u0442\u0430\u043c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u0435\u0441\u0441\u0438\u0439 \u0438 \u043a\u0443\u043a\u0438, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e jwt, \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e \u044f \u0431\u044b\u043b \u0443\u0434\u0438\u0432\u043b\u0451\u043d, \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u043d\u0435 \u043c\u043d\u043e\u0433\u043e \u0433\u0440\u0443\u0441\u0442\u043d\u043e\u0432\u0430\u0442\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u0437\u0430\u043f\u043e\u0441\u0442\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e, \u043e\u043d\u0438 \u0438\u0445 \u043d\u0435 \u0447\u0438\u0442\u0430\u044e\u0442, \u043d\u043e \u0434\u0430 \u043b\u0430\u0434\u043d\u043e, JWT \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u0433\u043e\u043d\u044f\u0435\u043c =)\u0427\u0442\u043e \u0436\u0435 \u0442\u0430\u043a\u043e\u0435 \u044d\u0442\u043e \u043d\u0430\u0448\u0435 JWT \u0438 \u0441 \u0447\u0435\u043c \u0435\u0433\u043e \u0435\u0434\u044f\u0442?JWT (Json web token) &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 3\u0445 \u0447\u0430\u0441\u0442\u0435\u0439: 1 &#8212; header (\u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c), 2 &#8212; payload (\u0434\u0430\u043d\u044b\u043d\u0435) \u0438 3 &#8212; signatere(\u043f\u043e\u0434\u043f\u0438\u0441\u044c).\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043a\u0430 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c? \u0447\u0442\u043e \u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0435? \u0447\u0442\u043e \u0437\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u044c?header (\u0438\u043b\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c) &#8212; \u044d\u0442\u043e json \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 Base64Url (\u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Base64, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 url-\u0430\u0434\u0440\u0435\u0441\u0430\u0445 \u0438 \u0438\u043c\u0435\u043d\u0430\u0445 \u0444\u0430\u0439\u043b\u043e\u0432), \u043e\u043d \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 HS256 \u0438\u043b\u0438 RS256) \u0438 \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e jwt).\u0415\u0441\u043b\u0438 \u0435\u0433\u043e \u0440\u0430\u0441\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c json \u0432 \u0432\u0438\u0434\u0435:{    &#171;alg&#187; : &#171;HS256&#187;,    &#171;typ&#187; : &#171;JWT&#187;}\u041e\u043d \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u043a\u0430\u043a\u0438\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u044c.Payload (\u0438\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435) &#8212; \u044d\u0442\u043e \u0442\u043e\u0436\u0435 json \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 Base64Url, \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f claims &#8212; \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u0441\u0435\u0441\u0441\u0438\u0438.\u0415\u0441\u043b\u0438 \u043c\u044b \u0435\u0433\u043e \u0440\u0430\u0441\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0447\u0442\u043e-\u0442\u043e \u0442\u0430\u043a\u043e\u0435:{       &#171;sub&#187;: &#171;user1&#187;,       &#171;role&#187;: &#171;admin&#187;,       &#171;exp&#187;: 1752480000 } * \u041d\u043e \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e payload \u043d\u0435 \u0448\u0438\u0444\u0440\u0443\u0435\u0442\u0441\u044f, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f &#8212;  \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u0435\u0433\u043e \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443 Base64 \u0438 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435. \u041f\u043e \u044d\u0442\u043e\u043c\u0443 \u0442\u0443\u0434\u0430 \u043d\u0435\u043b\u044c\u0437\u044f \u043a\u043b\u0430\u0441\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u0438 \u0438\/\u0438\u043b\u0438 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435! Signature (\u0438\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u044c) &#8212; \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u0448 \u0442\u043e\u043a\u0435\u043d \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u044b\u043c \u043e\u0442 \u043f\u043e\u0434\u0434\u0435\u043b\u043a\u0438. \u042d\u0442\u043e \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u0451\u043c \u0441\u043a\u043b\u0435\u0438\u0432\u0430\u043d\u0438\u044f payload \u0438 header \u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0447\u043a\u0443 \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u043d\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0440\u0432\u0435\u0440.\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:HMACSHA256(      base64UrlEncode(header) + &#171;.&#187; + base64UrlEncode(payload),   secret_key) HMAC-SHA256 &#8212; \u044d\u0442\u043e \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0445\u044d\u0448-\u0444\u0443\u043d\u043a\u0446\u0438\u044e SHA-265 \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c. \u0418 \u043e\u043d \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445, \u0437\u0430\u0449\u0438\u0449\u0430\u044f \u043e\u0442 \u043f\u043e\u0434\u0434\u0435\u043b\u043a\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435 \u043f\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u0430\u043d\u0430\u043b\u0430\u043c.\u0422\u043e \u0435\u0441\u0442\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0442\u043e\u043a\u0435\u043d: \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 header \u0438 payload, \u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442 \u0438\u0445, \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c &#8212; \u043f\u043e\u0434\u0443\u0447\u0430\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u044c. \u0417\u0430\u0442\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0443 (\u043e\u0431\u044b\u0447\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u043b\u043e\u0433\u0438\u043d\u0430). \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u043e\u043a\u0435\u043d \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 (\u043e\u0431\u044b\u0447\u043d\u043e \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 Authorization: Bearer &lt;\u0442\u043e\u043a\u0435\u043d&gt;). \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430\u043d\u043e\u0432\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u044c \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 header \u0438 payload \u0441 \u0442\u0435\u043c \u0436\u0435 \u0441\u0430\u043c\u044b\u043c \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b\u043b\u0430 \u0432 \u0442\u043e\u043a\u0435\u043d\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0448\u0451\u043b \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, JWT \u043d\u0435 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u043e \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0438\u0445 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u044c &#8212; \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0443.\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 session \u0438 jwt\u041c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u043d\u0430\u0435\u043c \u0438 \u043e \u0441\u0435\u0441\u0441\u0438\u044f\u0445, \u0438 \u043e jwt. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0434\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u0445 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c.1. \u0421\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 &#8212; \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0445\u043e\u0442\u044f \u0432 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f jwt \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u04352. \u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0442\u044f\u0436\u0435\u043b\u0435\u0435, \u043d\u0435\u0436\u0435\u043b\u0438 jwt, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0443\u0436\u0435\u043d \u043e\u0431\u0449\u0438\u0439 Redis3. \u041d\u043e \u043e\u0442\u043e\u0437\u0432\u0430\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u044e \u0438 \u043a\u0443\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0434\u043b\u044f \u043e\u0442\u0437\u044b\u0432\u0430 jwt \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0430\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u043a \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043d \u0441\u0430\u043c \u0441\u0442\u0430\u043d\u0435\u0442 \u043d\u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c.4. \u0421\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u044f\u0437\u0432\u0438\u043c\u044b \u043a CSRF \u0430\u0442\u0430\u043a\u0435, \u043d\u043e jwt \u043a \u043d\u0435\u0439 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435 \u0443\u044f\u0437\u0432\u0438\u043c.5. \u0421\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u0443\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u0438 MPA (Multi-Page Application), \u0430 jwt \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445 \u0438 SPA (Single Page Application)\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430, \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u0434 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0438\u0437 3\u0445 \u0441\u0442\u0440\u043e\u043a. \u0418 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 application.properties:\/\/\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0434\u043b\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 HMAC-SHA256SecretKey key = Jwts.SIG.HS256.key().build();\/\/\u041f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 application.propertiesString base64 = Encoders.BASE64.encode(key.getEncoded());System.out.println(base64);\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432 \u0441\u0430\u043c\u043e\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 @SpringBootApplication. \u0412 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 SecurityCourseApplication. \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u0434\u043e\u043a\u0435\u0440 \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d) \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043d\u0430\u043c \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430\u0412 \u0441\u0430\u043c\u043e\u0439 \u043d\u0438\u0436\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 application.properties \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043d\u043e\u0432\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a:#\u0421\u0430\u043c \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447jwt-secret=fdLwz0v0J3UQDrb+DJl2+618BLj24xPq+ZZkU95uUsQ=#\u0412\u0440\u0435\u043c\u044f \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0440\u043e\u0447\u0435 jwt \u0442\u043e\u043a\u0435\u043d \u0438\u0441\u0442\u0435\u0447\u0451\u0442 (\u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445)jwt-expiration=3600000#\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u0440\u043e\u043a\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (\u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445)jwt-refresh-expiration=604800000\u041d\u0443 \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u043e\u0442 \u043a\u043e\u0434 \u0438\u0437 3\u0445 \u0441\u0442\u0440\u043e\u043a \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0438\u0437-\u0437\u0430 \u043d\u0435\u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438.\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a java-code \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432.JwtService &#8212; \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 sevice, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 JwtService \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433.@Servicepublic class JwtService {    @Value(&#171;${jwt-secret}&#187;)    private String secretKey;    @Value(&#171;${jwt-expiration}&#187;)    private long jwtExpiration;    \/\/\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b    private SecretKey getSigningKey(){        \/\/\u041f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 SecretKey, \u043a\u043e\u0442\u043e\u0440\u044b\u043c        \/\/jjwt (java json web token) \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b        byte[] keyBytes = Decoders.BASE64.decode(secretKey);        \/\/\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043a\u043b\u044e\u0447 \u0434\u043b\u044f HMAC-SHA256 \u043f\u043e\u0434\u043f\u0438\u0441\u0438        return Keys.hmacShaKeyFor(keyBytes);    }    \/\/\u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0435\u0433\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u044c \u0438 \u0434\u043e\u0441\u0442\u0430\u0451\u0442 \u0438\u0437 \u043d\u0435\u0433\u043e \u0432\u0441\u0435 claims (payload)    \/\/\u0415\u0441\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u044c \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0438\u043b\u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0442\u043e\u043a\u0435\u043d\u0430 \u043d\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 &#8212; \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435    \/\/\u042d\u0422\u041e \u0415\u0414\u0418\u041d\u0421\u0422\u0412\u0415\u041d\u041d\u041e\u0415 \u041c\u0415\u0421\u0422\u041e \u0413\u0414\u0415 \u041f\u0420\u041e\u0418\u0421\u0425\u041e\u0414\u0418\u0422 \u041a\u0420\u0418\u041f\u0422\u041e\u0413\u0420\u0410\u0424\u0418\u0427\u0415\u0421\u041a\u0410\u042f \u041f\u0420\u041e\u0412\u0415\u0420\u041a\u0410 \u0422\u041e\u041a\u0415\u041d\u0410    private Claims extractAllClaims(String token){        return Jwts.parser()                .verifyWith(getSigningKey()) \/\/\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447                .build()                .parseSignedClaims(token) \/\/ !\u043f\u0430\u0440\u0441\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u044c!                .getPayload(); \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c payload    }    \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442: \u0438\u0441\u0442\u0451\u043a \u043b\u0438 \u0442\u043e\u043a\u0435\u043d    private boolean isTokenExpired(String token){        \/\/extractAllClaims(token).getExpiration() &#8212; \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 Date, \u0438\u0437\u0432\u043b\u0435\u0447\u0451\u043d\u043d\u044b\u0439 \u0438\u0437 claim&#8217;\u0430        \/\/ exp \u0442\u043e\u043a\u0435\u043d\u0430. (\u0412\u0440\u0435\u043c\u044f \u043a\u043e\u0433\u0434\u0430 \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0442\u0430\u0442\u044c \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c)        \/\/.before(new Date()) &#8212; \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true, \u0435\u0441\u043b\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c new Date()        \/\/ \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0449\u0435, \u0442\u043e &#8212; \u00ab\u0414\u0430\u0442\u0430 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0441\u0435\u0439\u0447\u0430\u0441?\u00bb \u0435\u0441\u043b\u0438 \u0434\u0430, \u0437\u043d\u0430\u0447\u0438\u0442 \u0441\u0440\u043e\u043a \u0443\u0436\u0435 \u043f\u0440\u043e\u0448\u0451\u043b, \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u043e\u0441\u0440\u043e\u0447\u0435\u043d.        return extractAllClaims(token).getExpiration().before(new Date());    }    \/\/\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b    \/\/\u0414\u043e\u0441\u0442\u0430\u0451\u0442 username \u0438\u0437 claim&#8217;\u0430 \u0442\u043e\u043a\u0435\u043d\u0430 (claim &#171;sub&#187; -&gt; subject)    \/\/\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0437\u0430 \u043a\u043e\u0433\u043e \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0443, \u0435\u0449\u0451 \u0434\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u043a\u0435\u043d\u0430.    public String extractUsername(String token){        return extractAllClaims(token).getSubject();    }    \/\/\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 jwt \u0442\u043e\u043a\u0435\u043d \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430    \/\/\u0412 payload \u043a\u043b\u0430\u0434\u0443\u0442\u0441\u044f: subject, \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f    \/\/\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u043e\u043b\u0435\u0439 &#8212; \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u0443 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0431\u0434.    \/\/\u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 extractClaims &#8212; \u0434\u043e\u043f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f payload    \/\/UserDetails &#8212; \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d    public String generateToken(Map&lt;String, Objects&gt; extractClaims, UserDetails userDetails){        return Jwts.builder()                \/\/\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 payload \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 claims                .claims(extractClaims)                \/\/\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 claim &#171;sub&#187; &#8212; \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f                .subject(userDetails.getUsername())                \/\/\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 &#171;iat&#187; &#8212; \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430                .issuedAt(new Date())                \/\/\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 &#171;exp&#187;- \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430                .expiration(new Date(System.currentTimeMillis() + jwtExpiration))                \/\/\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 claim &#171;roles&#187; \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043f\u0440\u0430\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f                .claim(&#171;roles&#187;, userDetails.getAuthorities().stream()                        \/\/\u0414\u043e\u0441\u0442\u0430\u0451\u043c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u043e\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: &#171;ROLE_USER&#187;                        .map(GrantedAuthority::getAuthority)                        \/\/\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0440\u043e\u043b\u0438 \u0432 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 List&lt;String&gt;                        .collect(Collectors.toList()))                \/\/\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c                .signWith(getSigningKey())                \/\/\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0451 \u0432 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443                .compact();    }    \/\/\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 jwt \u0442\u043e\u043a\u0435\u043d, \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 claims    \/\/\u041f\u043e \u0441\u0443\u0442\u0438 \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0432\u044b\u0448\u0435    public String generateToken(UserDetails userDetails){        return generateToken(new HashMap&lt;&gt;(), userDetails);    }    \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0438 \u0441\u0440\u043e\u043a \u043d\u0435 \u0438\u0441\u0442\u0451\u043a    public boolean isTokenValid(String token, UserDetails userDetails){        final String username = extractUsername(token); \/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c username \u0438\u0437 userDetails        \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0442\u043e\u043a\u0435\u043d \u043d\u0430 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u0440\u043e\u043a\u0430        return username.equals(userDetails.getUsername()) &amp;&amp; !isTokenExpired(token);    }}\u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u043d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c, \u0438 \u0432 \u0446\u0435\u043b\u043e\u043c \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u0436\u0435 \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0441\u043b\u043e\u0436\u043d\u043e)JwtAuthenticationFilterJwtAuthenticationFilter \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 JwtServise, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442. \u0424\u0438\u043b\u044c\u0442\u0440 \u0447\u0438\u0442\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 Authorization: Bearer &lt;\u0442\u043e\u043a\u0435\u043d&gt;, \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u0438 \u043a\u043b\u0430\u0434\u0451\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432 SecurityContext.\u0422\u0435\u043f\u0435\u0440\u044c \u0432 \u043f\u0430\u043f\u043a\u0435 config \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u043a\u0435\u0442:  filter \u0438 \u0443\u0436\u0435 \u0432 \u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c JwtAuthenticationFilter.@Component@RequiredArgsConstructorpublic class JwtAuthenticationFilter extends OncePerRequestFilter {    private final JwtService jwtService;    private final UserDetailsServiceImpl userDetailsService;    @Override    protected void doFilterInternal(HttpServletRequest request,                                    HttpServletResponse response,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-487275","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/487275","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=487275"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/487275\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=487275"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=487275"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=487275"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}