{"id":354266,"date":"2024-05-20T22:45:07","date_gmt":"2024-05-20T22:45:07","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=354266"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=354266","title":{"rendered":"<span>\u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0432 KeyCloak \u0438 \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442.<\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u043f\u043e\u043a\u0430\u0436\u0435\u043c \u0432\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u0432 Keycloak \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440.<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u0432\u0441\u0435 \u0437\u043d\u0430\u0435\u0442\u0435, Keycloak \u2013 \u044d\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0432\u044b\u043a\u0430\u043c\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 Java) \u0438 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 Identity Provider \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c OIDC \u0438 SAML.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c \u043d\u0430\u0431\u043e\u0440\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432. \u041d\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u043b\u043e\u0433\u0438\u043a\u0443? <a href=\"https:\/\/www.keycloak.org\/docs\/latest\/server_development\/#_auth_spi\"><u>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/u><\/a> \u0434\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442: \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0430\u043c\u043e\u043c\u0443.<\/p>\n<p>\u0427\u0442\u043e \u043c\u044b \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0430\u0448\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0438\u0431\u0435\u0440\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u041a2\u0422\u0435\u0445 \u0415\u0433\u043e\u0440\u043e\u043c \u0422\u0443\u0440\u043a\u0438\u043d\u044b\u043c \u0432 \u0438\u0442\u043e\u0433\u0435 \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438.<\/p>\n<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b23\/327\/442\/b23327442841b0a2aa4adea7c6555050.png\" width=\"822\" height=\"666\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b23\/327\/442\/b23327442841b0a2aa4adea7c6555050.png\"\/><\/figure>\n<p>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 jar-\u0444\u0430\u0439\u043b, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c (\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438). \u0415\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443, \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435:\u2026\/keycloak-21.0.2\/providers<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c bin\/kc.sh build<\/p>\n<p>\u0418 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 \u043e\u0431\u0449\u0435\u043c \u043f\u0435\u0440\u0435\u0447\u043d\u0435. \u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<h2>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u0442\u0435\u043d\u0434\u0430<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e REST API \u043a \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442 \u043d\u0435\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0435\u043d\u0434:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/356\/f84\/dda\/356f84ddafecddf96d420cc6d94c9470.png\" width=\"1122\" height=\"891\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/356\/f84\/dda\/356f84ddafecddf96d420cc6d94c9470.png\"\/><\/figure>\n<h2>\u041a\u043b\u0438\u0435\u043d\u0442<\/h2>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0446\u0435\u043b\u0435\u0432\u043e\u0433\u043e \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c apache2 \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u043c\u043e\u0434\u0443\u043b\u0435\u043c mod_auth_openidc, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u043c \u0435\u043c\u0443 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 OIDC-\u043a\u043b\u0438\u0435\u043d\u0442\u0430: <a href=\"https:\/\/github.com\/OpenIDC\/mod_auth_openidc\"><u>https:\/\/github.com\/OpenIDC\/mod_auth_openidc<\/u><\/a>\u00a0<\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Apache2 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code>&lt;VirtualHost *:80>     # The ServerName directive sets the request scheme, hostname and port that     # the server uses to identify itself. This is used when creating \u00a0\u00a0\u00a0\u00a0# redirection URLs. In the context of virtual hosts, the ServerName \u00a0\u00a0\u00a0\u00a0# specifies what hostname must appear in the request's Host: header to \u00a0\u00a0\u00a0\u00a0# match this virtual host. For the default virtual host (this file) this \u00a0\u00a0\u00a0\u00a0# value is not decisive as it is used as a last resort host regardless. \u00a0\u00a0\u00a0\u00a0# However, you must set it for any further virtual host explicitly. \u00a0\u00a0\u00a0\u00a0#ServerName www.example.com  \u00a0\u00a0\u00a0\u00a0ServerAdmin webmaster2@localhost \u00a0\u00a0\u00a0\u00a0DocumentRoot \/var\/www\/askar_test \u00a0\u00a0\u00a0\u00a0ServerName askar.test.local  \u00a0\u00a0\u00a0\u00a0#this is required by mod_auth_openidc     OIDCSSLValidateServer Off\u00a0 \u00a0\u00a0\u00a0\u00a0OIDCProviderMetadataURL https:\/\/mykeycloak:8443\/realms\/master\/.well-known\/openid-configuration \u00a0\u00a0\u00a0\u00a0OIDCClientID apache2 \u00a0\u00a0\u00a0\u00a0OIDCClientSecret 7JNzjSh060t7ddBKLhlZ4oMp2jltDZae \u00a0\u00a0\u00a0\u00a0OIDCRedirectURI http:\/\/askar.test.local\/index.html      # maps the preferred_username claim to the REMOTE_USER environment variable     OIDCRemoteUserClaim preferred_username      &lt;Location \/>         AuthType openid-connect   \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Require valid-user \u00a0\u00a0\u00a0\u00a0&lt;\/Location>   \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ErrorLog ${APACHE_LOG_DIR}\/error.log \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CustomLog ${APACHE_LOG_DIR}\/access.log combined &lt;\/VirtualHost><\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u0432 \u0446\u0435\u043b\u044f\u0445 \u0442\u0435\u0441\u0442\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u043e SSL \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043f\u0446\u0438\u0438 OIDCSSLValidateServer Off. \u0412 \u043f\u0440\u043e\u0434\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043b\u044c\u0437\u044f.<\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0430\u0439\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u043c php-\u0444\u0430\u0439\u043b\u0438\u043a:<\/p>\n<pre><code class=\"php\">&lt;!DOCTYPE html> &lt;html lang=\"en\"> &lt;head>     &lt;meta charset=\"utf-8\">     &lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">   \u00a0\u00a0&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> \u00a0\u00a0\u00a0 &lt;meta name=\"description\" content=\"\"> \u00a0\u00a0\u00a0 &lt;meta name=\"author\" content=\"\"> \u00a0\u00a0\u00a0 &lt;title>OpenID Connect: Received Claims&lt;\/title> &lt;\/head>  &lt;body>     &lt;h3>     \u00a0\u00a0\u00a0\u00a0Claims sent back from OpenID Connect via the Apache module \u00a0\u00a0\u00a0\u00a0&lt;\/h3> \u00a0\u00a0\u00a0\u00a0&lt;br\/> \u00a0\u00a0\u00a0&lt;!-- OpenAthens attribtues --> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php session_start(); ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h2>Claims&lt;\/h2> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;br\/> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div class=\"row\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;table class=\"table\" style=\"width:80%;\" border=\"1\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php foreach ($_SERVER as $key => $value): ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php if (preg_match(\"\/OIDC_\/i\", $key)): ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;tr> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td data-toggle=\"tooltip\" title=&lt;?php echo $key; ?>>&lt;?php echo $key; ?>&lt;\/td> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td data-toggle=\"tooltip\" title=&lt;?php echo $value; ?>>&lt;?php echo $value; ?>&lt;\/td> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/tr> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php endif; ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php endforeach; ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/table> &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>\u0412\u0437\u044f\u043b\u0438 \u043e\u0442\u0441\u044e\u0434\u0430: <a href=\"https:\/\/docs.openathens.net\/providers\/apache-openid-connect-example\"><u>https:\/\/docs.openathens.net\/providers\/apache-openid-connect-example<\/u><\/a>\u00a0<\/p>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0442\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.<\/p>\n<h2>\u0421\u0442\u043e\u0440\u043e\u043d\u043d\u044f\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430<\/h2>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c OpenResty <a href=\"https:\/\/openresty.org\/\"><u>https:\/\/openresty.org\/<\/u><\/a><\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0445\u043e\u0434\u0430 \u043e\u0436\u0438\u0434\u0430\u0435\u043c json, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 {&#8216;username&#8217;: &lt;\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f> }, \u0430 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e Allow \u0438\u043b\u0438 Deny.<\/p>\n<p>\u0412 \u0446\u0435\u043b\u044f\u0445 \u0442\u0435\u0441\u0442\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f, \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043b\u0438 \u0438\u0445 \u0432 whitelisted_names.<\/p>\n<p>\u0412\u0430\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043a\u0430\u043f\u0440\u0438\u0437\u043d\u044b\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b\u0438 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430: access_log\u00a0 \/var\/log\/nginx\/postdata.log\u00a0 postdata<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/af7\/43e\/61e\/af743e61eccff04879ceb5147a7df998.png\" width=\"981\" height=\"105\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/af7\/43e\/61e\/af743e61eccff04879ceb5147a7df998.png\"\/><\/figure>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446 \u0443\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u0435\u0433\u043e \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 =)<\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code>http {  \u2026  server { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0listen *:8082; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0server_name _; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0location \/reply\/ { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0access_log\u00a0 \/var\/log\/nginx\/postdata.log\u00a0 postdata; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0error_log \/var\/log\/nginx\/error_openresty.log; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0content_by_lua_block { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0whitelisted_names = { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'test', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'gimli', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'torin' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.req.read_body() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local cjson = require \"cjson\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local body = ngx.req.get_body_data() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local data = cjson.decode(body) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local username = data[\"username\"] \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = false \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for index, value in ipairs(whitelisted_names) do \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if value == username then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = true \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if flag then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Allow\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Deny\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end }  \u2026  }  http {  \u2026  server { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0listen *:8082; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0server_name _; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0location \/reply\/ { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0access_log\u00a0 \/var\/log\/nginx\/postdata.log\u00a0 postdata; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0error_log \/var\/log\/nginx\/error_openresty.log; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0content_by_lua_block { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0whitelisted_names = { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'test', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'gimli', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'torin' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.req.read_body() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local cjson = require \"cjson\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local body = ngx.req.get_body_data() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local data = cjson.decode(body) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local username = data[\"username\"] \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = false \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for index, value in ipairs(whitelisted_names) do \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if value == username then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = true \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if flag then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Allow\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Deny\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end }  \u2026  }<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cbe\/32e\/aec\/cbe32eaec4c21b45f76e28e6a46a97a4.png\" width=\"734\" height=\"94\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cbe\/32e\/aec\/cbe32eaec4c21b45f76e28e6a46a97a4.png\"\/><\/figure>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 =)<\/p>\n<h2>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u0430\u043c Keycloak<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442 Apache2. Client id \u0438 Client Secret \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 Apache2<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/11b\/490\/48c\/11b49048ccae90292b153eac839b4be1.png\" width=\"1051\" height=\"524\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/11b\/490\/48c\/11b49048ccae90292b153eac839b4be1.png\"\/><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 flow \u0438 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 Advanced \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0443<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bab\/042\/7e0\/bab0427e05c6df92ca1314b2dd5f10d9.png\" width=\"1025\" height=\"229\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bab\/042\/7e0\/bab0427e05c6df92ca1314b2dd5f10d9.png\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f3d\/db1\/3d9\/f3ddb13d91a5e3d7c577b679f6c79930.png\" width=\"1011\" height=\"317\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f3d\/db1\/3d9\/f3ddb13d91a5e3d7c577b679f6c79930.png\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<p>\u0422\u0435\u043a\u0441\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u0439 \u2013 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0438.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 <code>TestAuthenticator3<\/code> \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>Authenticator<\/code>. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f authenticate. \u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043d\u0451\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0439\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.\u00a0<\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0438\u043c\u0435\u043d\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0445 \u0438\u043c\u0435\u043d, \u0445\u0440\u0430\u043d\u0438\u043c\u043e\u043c \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0438\u043c\u044f, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>context.getUser()<\/code>. \u0417\u0430\u0442\u0435\u043c \u0438\u0437 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043c\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>getUsername()<\/code>. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0435\u0433\u043e \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0445, \u0438 \u0432\u044b\u0434\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>context.success<\/code>. \u0415\u0441\u043b\u0438 \u0436\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u043f\u0440\u043e\u0448\u0451\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>context.failure<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0438\u043f \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/www.keycloak.org\/docs\/latest\/server_development\/#implementing-an-authenticator\"><u>\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/u><\/a>.\u00a0<\/p>\n<p>\u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c. URL \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0418\u0421, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441, \u0437\u0430\u0434\u0430\u043d \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043e\u0439.<\/p>\n<p>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440:<\/p>\n<pre><code class=\"java\">public class TestAuthenticator3 implements Authenticator {     private static final Logger logger = Logger.getLogger(k2.test.keycloak.authenticator.TestAuthenticator3.class);          @Override      public void authenticate(AuthenticationFlowContext context) {         var user = context.getUser();          var username = user.getUsername() try {             var res = sendPOST(username);             System.out.println(\"Got response: \" + res);             if (res.contains(\"Allow\")) {                 System.out.println(\"Response Allow\");                 context.success();             } else {                 System.out.println(\"Response Deny \u2013 else path \");                 context.failure(AuthenticationFlowError.CLIENT_DISABLED);             }         } catch (Exception e) {             context.failure(AuthenticationFlowError.INTERNAL_ERROR);             System.out.println(\"Exception path\");         }     }      private static final String USER_AGENT = \"Mozilla\/5.0\";     private static final String POST_URL = \"http:\/\/172.31.80.26:8082\/reply\/\";      private static String sendPOST(String username) throws IOException {         URL obj = new URL(POST_URL);         HttpURLConnection con = (HttpURLConnection) obj.openConnection();         con.setRequestMethod(\"POST\");         con.setRequestProperty(\"User-Agent\", USER_AGENT); \/\/ POST\u00a0 \u00a0          con.setDoOutput(true);         OutputStream os = con.getOutputStream();         var request = \"{\\\"username\\\":\\\"\" + username + \"\\\"}\";         os.write(request.getBytes());         os.flush();         os.close(); \/\/ POST - END\u00a0 \u00a0          int responseCode = con.getResponseCode();         System.out.println(\"POST Response Code :: \" + responseCode);         if (responseCode == HttpURLConnection.HTTP_OK) { \/\/success\u00a0 \u00a0 \u00a0 \u00a0              BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));             String inputLine;             StringBuffer response = new StringBuffer();             while ((inputLine = in.readLine()) != null) {                 response.append(inputLine);             }             in.close();             System.out.println(\"POST Response Text :: \" + response.toString());             return response.toString();         } else {             System.out.println(\"POST Response Text else path :: \");             return \"Error\";         }     }  }<\/code><\/pre>\n<p>AuthenticationFactory \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0438 \u0435\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 Keycloak. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b Keycloak \u0443\u0432\u0438\u0434\u0435\u043b \u043d\u0430\u0448 \u043d\u043e\u0432\u044b\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440.<\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438: <a href=\"https:\/\/www.keycloak.org\/docs\/latest\/server_development\/#implementing-an-authenticatorfactory\"><u>https:\/\/www.keycloak.org\/docs\/latest\/server_development\/#implementing-an-authenticatorfactory<\/u><\/a>.\u00a0<\/p>\n<p>\u0424\u0430\u043a\u0442\u043e\u0440\u0438:<\/p>\n<pre><code class=\"java\">public class TestAuthenticator3Factory implements AuthenticatorFactory {     public static final String ID = \"TestAuthenticator 3\";     private static final Authenticator AUTHENTICATOR_INSTANCE = new TestAuthenticator3();     static final String MESSAGE_CONFIG = \"message_to_show_3\";      @Override  public Authenticator create(KeycloakSession keycloakSession) {         return AUTHENTICATOR_INSTANCE;     }      @Override public String getDisplayType() {         return \" TestAuthenticator3\";     }      @Override public boolean isConfigurable() {         return true;     }      @Override  public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {         return new AuthenticationExecutionModel.Requirement[] {             AuthenticationExecutionModel.Requirement.REQUIRED         };     }      @Override  public boolean isUserSetupAllowed() {         return false;     }      @Override  public String getHelpText() {         return \"Test Authentication flow\";     }      @Override  public List &lt; ProviderConfigProperty > getConfigProperties() {         ProviderConfigProperty name = new ProviderConfigProperty();         name.setType(STRING_TYPE);         name.setName(MESSAGE_CONFIG);         name.setLabel(\"Just empty label\");         name.setHelpText(\"Any help text\");         return Collections.singletonList(name);     }      @Override public String getReferenceCategory() {         return null;     }      @Override public void init(Config.Scope scope) {}      @Override public void postInit(KeycloakSessionFactory keycloakSessionFactory) {}      @Override public void close() {}      @Override  public String getId() {         return ID;     } }<\/code><\/pre>\n<p>\u0421\u0442\u0440\u043e\u0438\u043c \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 flow.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/417\/66e\/e2f\/41766ee2fe0ba901bf1fc24ba859b43d.png\" width=\"1309\" height=\"409\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/417\/66e\/e2f\/41766ee2fe0ba901bf1fc24ba859b43d.png\"\/><\/figure>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u0432\u0438\u0434\u0438\u043c \u043d\u0430 Apache.<\/p>\n<p>\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430:<\/p>\n<p><code>62.217.191.91 - gimli [14\/Jun\/2023:16:21:12 +0300] \"GET \/info2.php HTTP\/1.1\" 200 2462 \"-\" \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/114.0.0.0 Safari\/537.36\"<\/code><\/p>\n<p><code>62.217.191.91 - - [14\/Jun\/2023:16:21:26 +0300] \"GET \/ HTTP\/1.1\" 302 1571 \"-\" \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/114.0.0.0 Safari\/537.36\"<\/code><\/p>\n<p><code>62.217.191.91 - gimli [14\/Jun\/2023:16:21:32 +0300] \"GET \/info.php?state=0CQZYZmW5jWpUlb4xbeqk2VcIs4&amp;session_state=e4058c19-9a58-4e98-8d97-fbcb6966d0b8&amp;code=9e76fced-42c9-454f-85d0-6d7a652da3e4.e4058c19-9a58-4e98-8d97-fbcb6966d0b8.098780c7-759e-41a3-96ce-d3837e1790a3 HTTP\/1.1\" 302 754 \"-\" \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/114.0.0.0 Safari\/537.36\"<\/code><\/p>\n<p><code>62.217.191.91 - gimli [14\/Jun\/2023:16:21:32 +0300] \"GET \/ HTTP\/1.1\" 200 5381 \"-\" \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/114.0.0.0 Safari\/537.36\"<\/code><\/p>\n<p><code>62.217.191.91 - gimli [14\/Jun\/2023:16:21:32 +0300] \"GET \/index.files\/image002.jpg HTTP\/1.1\" 200 47910 \"http:\/\/askar.test.local\/\" \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/114.0.0.0 Safari\/537.36\"<\/code><\/p>\n<p><code>62.217.191.91 - gimli [14\/Jun\/2023:16:21:38 +0300] \"GET \/info2.php HTTP\/1.1\" 200 2360 \"-\" \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/114.0.0.0 Safari\/537.36\"<\/code><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b85\/5ac\/861\/b855ac861fbfbe75f566a32da0401cab.png\" width=\"745\" height=\"763\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b85\/5ac\/861\/b855ac861fbfbe75f566a32da0401cab.png\"\/><\/figure>\n<p>\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430<\/p>\n<p><code>2023-06-14 16:33:16,184 WARN\u00a0 [org.keycloak.events] (executor-thread-98) type=LOGIN_ERROR, realmId=69bd9151-dd74-470a-ba27-1a660799fcf2, clientId=apache2, userId=null, ipAddress=62.217.191.91, error=invalid_user_credentials, auth_method=openid-connect, auth_type=code, redirect_uri=http:\/\/askar.test.local\/info.php, code_id=729202ce-a308-458c-bfe0-767fd9349d69, username=legolas, authSessionParentId=729202ce-a308-458c-bfe0-767fd9349d69, authSessionTabId=GQPjo8i5d6A<\/code><\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/76c\/a1d\/e8e\/76ca1de8eb9a131239cfe33afcbe9fd2.png\" width=\"416\" height=\"311\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/76c\/a1d\/e8e\/76ca1de8eb9a131239cfe33afcbe9fd2.png\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2e0\/bb5\/f9a\/2e0bb5f9a09d1f93d89bcad596524429.png\" width=\"657\" height=\"391\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2e0\/bb5\/f9a\/2e0bb5f9a09d1f93d89bcad596524429.png\"\/><\/figure>\n<h2>\u0412\u044b\u0432\u043e\u0434<\/h2>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0432\u00a0KeyCloak, \u0430\u00a0\u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0432\u0435\u0431\u2011\u0441\u0435\u0440\u0432\u0435\u0440 Apache \u0438 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044e\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0438 \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u043b\u0438 \u0435\u0435 \u0441\u00a0KeyCloak.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/759600\/\"> https:\/\/habr.com\/ru\/articles\/759600\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442.<\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u043f\u043e\u043a\u0430\u0436\u0435\u043c \u0432\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u0432 Keycloak \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440.<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u0432\u0441\u0435 \u0437\u043d\u0430\u0435\u0442\u0435, Keycloak \u2013 \u044d\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0432\u044b\u043a\u0430\u043c\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 Java) \u0438 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 Identity Provider \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c OIDC \u0438 SAML.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c \u043d\u0430\u0431\u043e\u0440\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432. \u041d\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u043b\u043e\u0433\u0438\u043a\u0443? <a href=\"https:\/\/www.keycloak.org\/docs\/latest\/server_development\/#_auth_spi\"><u>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/u><\/a> \u0434\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442: \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0430\u043c\u043e\u043c\u0443.<\/p>\n<p>\u0427\u0442\u043e \u043c\u044b \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0430\u0448\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0438\u0431\u0435\u0440\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u041a2\u0422\u0435\u0445 \u0415\u0433\u043e\u0440\u043e\u043c \u0422\u0443\u0440\u043a\u0438\u043d\u044b\u043c \u0432 \u0438\u0442\u043e\u0433\u0435 \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438.<\/p>\n<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 jar-\u0444\u0430\u0439\u043b, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c (\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438). \u0415\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443, \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435:\u2026\/keycloak-21.0.2\/providers<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c bin\/kc.sh build<\/p>\n<p>\u0418 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 \u043e\u0431\u0449\u0435\u043c \u043f\u0435\u0440\u0435\u0447\u043d\u0435. \u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<h2>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u0442\u0435\u043d\u0434\u0430<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e REST API \u043a \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442 \u043d\u0435\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0435\u043d\u0434:<\/p>\n<figure class=\"full-width\"><\/figure>\n<h2>\u041a\u043b\u0438\u0435\u043d\u0442<\/h2>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0446\u0435\u043b\u0435\u0432\u043e\u0433\u043e \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c apache2 \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u043c\u043e\u0434\u0443\u043b\u0435\u043c mod_auth_openidc, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u043c \u0435\u043c\u0443 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 OIDC-\u043a\u043b\u0438\u0435\u043d\u0442\u0430: <a href=\"https:\/\/github.com\/OpenIDC\/mod_auth_openidc\"><u>https:\/\/github.com\/OpenIDC\/mod_auth_openidc<\/u><\/a>\u00a0<\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Apache2 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code>&lt;VirtualHost *:80>     # The ServerName directive sets the request scheme, hostname and port that     # the server uses to identify itself. This is used when creating \u00a0\u00a0\u00a0\u00a0# redirection URLs. In the context of virtual hosts, the ServerName \u00a0\u00a0\u00a0\u00a0# specifies what hostname must appear in the request's Host: header to \u00a0\u00a0\u00a0\u00a0# match this virtual host. For the default virtual host (this file) this \u00a0\u00a0\u00a0\u00a0# value is not decisive as it is used as a last resort host regardless. \u00a0\u00a0\u00a0\u00a0# However, you must set it for any further virtual host explicitly. \u00a0\u00a0\u00a0\u00a0#ServerName www.example.com  \u00a0\u00a0\u00a0\u00a0ServerAdmin webmaster2@localhost \u00a0\u00a0\u00a0\u00a0DocumentRoot \/var\/www\/askar_test \u00a0\u00a0\u00a0\u00a0ServerName askar.test.local  \u00a0\u00a0\u00a0\u00a0#this is required by mod_auth_openidc     OIDCSSLValidateServer Off\u00a0 \u00a0\u00a0\u00a0\u00a0OIDCProviderMetadataURL https:\/\/mykeycloak:8443\/realms\/master\/.well-known\/openid-configuration \u00a0\u00a0\u00a0\u00a0OIDCClientID apache2 \u00a0\u00a0\u00a0\u00a0OIDCClientSecret 7JNzjSh060t7ddBKLhlZ4oMp2jltDZae \u00a0\u00a0\u00a0\u00a0OIDCRedirectURI http:\/\/askar.test.local\/index.html      # maps the preferred_username claim to the REMOTE_USER environment variable     OIDCRemoteUserClaim preferred_username      &lt;Location \/>         AuthType openid-connect   \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Require valid-user \u00a0\u00a0\u00a0\u00a0&lt;\/Location>   \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ErrorLog ${APACHE_LOG_DIR}\/error.log \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CustomLog ${APACHE_LOG_DIR}\/access.log combined &lt;\/VirtualHost><\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u0432 \u0446\u0435\u043b\u044f\u0445 \u0442\u0435\u0441\u0442\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u043e SSL \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043f\u0446\u0438\u0438 OIDCSSLValidateServer Off. \u0412 \u043f\u0440\u043e\u0434\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043b\u044c\u0437\u044f.<\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0430\u0439\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u043c php-\u0444\u0430\u0439\u043b\u0438\u043a:<\/p>\n<pre><code class=\"php\">&lt;!DOCTYPE html> &lt;html lang=\"en\"> &lt;head>     &lt;meta charset=\"utf-8\">     &lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">   \u00a0\u00a0&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> \u00a0\u00a0\u00a0 &lt;meta name=\"description\" content=\"\"> \u00a0\u00a0\u00a0 &lt;meta name=\"author\" content=\"\"> \u00a0\u00a0\u00a0 &lt;title>OpenID Connect: Received Claims&lt;\/title> &lt;\/head>  &lt;body>     &lt;h3>     \u00a0\u00a0\u00a0\u00a0Claims sent back from OpenID Connect via the Apache module \u00a0\u00a0\u00a0\u00a0&lt;\/h3> \u00a0\u00a0\u00a0\u00a0&lt;br\/> \u00a0\u00a0\u00a0&lt;!-- OpenAthens attribtues --> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php session_start(); ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h2>Claims&lt;\/h2> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;br\/> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div class=\"row\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;table class=\"table\" style=\"width:80%;\" border=\"1\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php foreach ($_SERVER as $key => $value): ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php if (preg_match(\"\/OIDC_\/i\", $key)): ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;tr> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td data-toggle=\"tooltip\" title=&lt;?php echo $key; ?>>&lt;?php echo $key; ?>&lt;\/td> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td data-toggle=\"tooltip\" title=&lt;?php echo $value; ?>>&lt;?php echo $value; ?>&lt;\/td> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/tr> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php endif; ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;?php endforeach; ?> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/table> &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>\u0412\u0437\u044f\u043b\u0438 \u043e\u0442\u0441\u044e\u0434\u0430: <a href=\"https:\/\/docs.openathens.net\/providers\/apache-openid-connect-example\"><u>https:\/\/docs.openathens.net\/providers\/apache-openid-connect-example<\/u><\/a>\u00a0<\/p>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0442\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.<\/p>\n<h2>\u0421\u0442\u043e\u0440\u043e\u043d\u043d\u044f\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430<\/h2>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c OpenResty <a href=\"https:\/\/openresty.org\/\"><u>https:\/\/openresty.org\/<\/u><\/a><\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0445\u043e\u0434\u0430 \u043e\u0436\u0438\u0434\u0430\u0435\u043c json, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 {&#8216;username&#8217;: &lt;\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f> }, \u0430 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e Allow \u0438\u043b\u0438 Deny.<\/p>\n<p>\u0412 \u0446\u0435\u043b\u044f\u0445 \u0442\u0435\u0441\u0442\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f, \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043b\u0438 \u0438\u0445 \u0432 whitelisted_names.<\/p>\n<p>\u0412\u0430\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043a\u0430\u043f\u0440\u0438\u0437\u043d\u044b\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b\u0438 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430: access_log\u00a0 \/var\/log\/nginx\/postdata.log\u00a0 postdata<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446 \u0443\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u0435\u0433\u043e \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 =)<\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code>http {  \u2026  server { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0listen *:8082; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0server_name _; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0location \/reply\/ { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0access_log\u00a0 \/var\/log\/nginx\/postdata.log\u00a0 postdata; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0error_log \/var\/log\/nginx\/error_openresty.log; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0content_by_lua_block { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0whitelisted_names = { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'test', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'gimli', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'torin' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.req.read_body() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local cjson = require \"cjson\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local body = ngx.req.get_body_data() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local data = cjson.decode(body) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local username = data[\"username\"] \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = false \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for index, value in ipairs(whitelisted_names) do \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if value == username then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = true \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if flag then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Allow\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Deny\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end }  \u2026  }  http {  \u2026  server { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0listen *:8082; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0server_name _; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0location \/reply\/ { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0access_log\u00a0 \/var\/log\/nginx\/postdata.log\u00a0 postdata; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0error_log \/var\/log\/nginx\/error_openresty.log; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0content_by_lua_block { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0whitelisted_names = { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'test', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'gimli', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'torin' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.req.read_body() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local cjson = require \"cjson\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local body = ngx.req.get_body_data() \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local data = cjson.decode(body) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0local username = data[\"username\"] \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = false \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for index, value in ipairs(whitelisted_names) do \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if value == username then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0flag = true \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if flag then \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Allow\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ngx.say(\"Deny\") \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0end }  \u2026  }<\/code><\/pre>\n<figure class=\"full-width\"><\/figure>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 =)<\/p>\n<h2>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u0430\u043c Keycloak<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442 Apache2. Client id \u0438 Client Secret \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 Apache2<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 flow \u0438 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 Advanced \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0443<\/p>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<p>\u0422\u0435\u043a\u0441\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u0439 \u2013 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0438.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 <code>TestAuthenticator3<\/code> \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>Authenticator<\/code>. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f authenticate. \u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043d\u0451\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0439\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.\u00a0<\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0438\u043c\u0435\u043d\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0445 \u0438\u043c\u0435\u043d, \u0445\u0440\u0430\u043d\u0438\u043c\u043e\u043c \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0438\u043c\u044f, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>context.getUser()<\/code>. \u0417\u0430\u0442\u0435\u043c \u0438\u0437 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043c\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>getUsername()<\/code>. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0435\u0433\u043e \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0445, \u0438 \u0432\u044b\u0434\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>context.success<\/code>. \u0415\u0441\u043b\u0438 \u0436\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u043f\u0440\u043e\u0448\u0451\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>context.failure<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0438\u043f \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/www.keycloak.org\/docs\/latest\/server_development\/#implementing-an-authenticator\"><u>\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/u><\/a>.\u00a0<\/p>\n<p>\u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c. URL \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0418\u0421, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441, \u0437\u0430\u0434\u0430\u043d \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043e\u0439.<\/p>\n<p>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440:<\/p>\n<pre><code class=\"java\">public class TestAuthenticator3 implements Authenticator {     private static final Logger logger = Logger.getLogger(k2.test.keycloak.authenticator.TestAuthenticator3.class);          @Override      public void authenticate(AuthenticationFlowContext context) {         var user = context.getUser();          var username = user.getUsername() try {             var res = sendPOST(username);             System.out.println(\"Got response: \" + res);             if (res.contains(\"Allow\")) {                 System.out.println(\"Response Allow\");                 context.success();             } else {                 System.out.println(\"Response Deny \u2013 else path \");                 context.failure(AuthenticationFlowError.CLIENT_DISABLED);             }         } catch (Exception e) {             context.failure(AuthenticationFlowError.INTERNAL_ERROR);             System.out.println(\"Exception path\");         }     }      private static final String USER_AGENT = \"Mozilla\/5.0\";     private static final String POST_URL = \"http:\/\/172.31.80.26:8082\/reply\/\";      private static String sendPOST(String username) throws IOException {         URL obj = new URL(POST_URL);         HttpURLConnection con = (HttpURLConnection) obj.openConnection();<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-354266","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/354266","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=354266"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/354266\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=354266"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=354266"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=354266"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}