{"id":206888,"date":"2013-12-21T20:40:03","date_gmt":"2013-12-21T16:40:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=206888"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=206888","title":{"rendered":"<span class=\"post_title\">\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Symfony2 \u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 Jira<\/span>"},"content":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435, \u0425\u0430\u0431\u0440\u043e\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Symfony2 \u0438 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 Jira.<\/p>\n<h4>\u0417\u0430\u0447\u0435\u043c \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c Jira \u0438 Symfony2?<\/h4>\n<p>  \u0412 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0433\u0434\u0435 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0441\u0430\u043f\u043f\u043e\u0440\u0442\u0430 \u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u0437\u0430\u0434\u0430\u0447 \u0447\u0435\u0440\u0435\u0437 API, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u044f\u0432\u043a\u0438 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b\u0442\u044c \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u044b \u0432 \u0442\u0438\u043a\u0435\u0442\u044b. \u041f\u0435\u0440\u0432\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u0441\u0442\u0430\u043b\u0430 \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u043f\u0443\u0442\u0438, \u0431\u044b\u043b\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Jira (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u201cBasic Authentication\u201d) \u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 Symfony2. \u0414\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439: <a href=\"http:\/\/symfony.com\/doc\/current\/book\/security.html\">http:\/\/symfony.com\/doc\/current\/book\/security.html<\/a>.<br \/>  <a name=\"habracut\"><\/a><\/p>\n<h4>\u0427\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 Symfony2?<\/h4>\n<p>  <\/p>\n<ol>\n<li> Token, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/li>\n<li> Listener, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/li>\n<li> Provider, \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Jira.<\/li>\n<li> User Provider, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f Symfony2 Security \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435.<\/li>\n<li> Factory, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/li>\n<\/ol>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0435\u043c Token<\/h4>\n<p>  \u0414\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438, \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 Symfony \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442\u0441\u044f \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 AbstractToken. \u0412 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c 2 \u043f\u043e\u043b\u044f \u2014 \u044d\u0442\u043e \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 Jira. \u041a\u043e\u0434 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<pre><code class=\"php\">&lt;?php  namespace DG\\JiraAuthBundle\\Security\\Authentication\\Token;  use Symfony\\Component\\Security\\Core\\Authentication\\Token\\AbstractToken;  class JiraToken extends AbstractToken {     protected $jira_login;     protected $jira_password;      public function __construct(array $roles = array('ROLE_USER')){         parent::__construct($roles);         $this-&gt;setAuthenticated(count($roles) &gt; 0);     }      public function getJiraLogin(){         return $this-&gt;jira_login;     }      public function setJiraLogin($jira_login){         $this-&gt;jira_login = $jira_login;     }      public function getJiraPassword(){         return $this-&gt;jira_password;     }      public function setJiraPassword($jira_password){         $this-&gt;jira_password = $jira_password;     }      public function serialize()     {         return serialize(array($this-&gt;jira_login, $this-&gt;jira_password, parent::serialize()));     }      public function unserialize($serialized)     {         list($this-&gt;jira_login, $this-&gt;jira_password, $parent_data) = unserialize($serialized);         parent::unserialize($parent_data);     }      public  function getCredentials(){         return '';     } } <\/code><\/pre>\n<h4>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Listener<\/h4>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0443 \u043d\u0430\u0441 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0438, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c Listener, \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 AbstractAuthenticationListener. <\/p>\n<pre><code class=\"php\">&lt;?php  namespace DG\\JiraAuthBundle\\Security\\Firewall;  use DG\\JiraAuthBundle\\Security\\Authentication\\Token\\JiraToken; use Symfony\\Component\\EventDispatcher\\EventDispatcherInterface; use Symfony\\Component\\HttpFoundation\\Request; use Symfony\\Component\\HttpFoundation\\Response; use Psr\\Log\\LoggerInterface; use Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationManagerInterface; use Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface; use Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException; use Symfony\\Component\\Security\\Core\\SecurityContextInterface; use Symfony\\Component\\Security\\Http\\Firewall\\AbstractAuthenticationListener;  class JiraListener extends AbstractAuthenticationListener {     protected function attemptAuthentication(Request $request){         if ($this-&gt;options['post_only'] && 'post' !== strtolower($request-&gt;getMethod())) {             if (null !== $this-&gt;logger) {                 $this-&gt;logger-&gt;debug(sprintf('Authentication method not supported: %s.', $request-&gt;getMethod()));             }              return null;         }          $username = trim($request-&gt;get($this-&gt;options['username_parameter'], null, true));         $password = $request-&gt;get($this-&gt;options['password_parameter'], null, true);          $request-&gt;getSession()-&gt;set(SecurityContextInterface::LAST_USERNAME, $username);         $request-&gt;getSession()-&gt;set('jira_auth', base64_encode($username.':'.$password));          $token = new JiraToken();         $token-&gt;setJiraLogin($username);         $token-&gt;setJiraPassword($password);          return $this-&gt;authenticationManager-&gt;authenticate($token);     } } <\/code><\/pre>\n<h4>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0432 Jira. Provider<\/h4>\n<p>  \u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u2014 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Jira. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 rest api \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 API Jira \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Buzz.<\/p>\n<pre><code class=\"php\">&lt;?php  namespace DG\\JiraAuthBundle\\Jira; use Buzz\\Message; use Buzz\\Client\\Curl;  class JiraRest {     private $jiraUrl = '';      public function __construct($jiraUrl){         $this-&gt;jiraUrl = $jiraUrl;     }      public function getUserInfo($username, $password){         $request = new Message\\Request(             'GET',             '\/rest\/api\/2\/user?username=' . $username,             $this-&gt;jiraUrl         );          $request-&gt;addHeader('Authorization: Basic ' . base64_encode($username . ':' . $password) );         $request-&gt;addHeader('Content-Type: application\/json');          $response = new Message\\Response();          $client = new Curl();         $client-&gt;setTimeout(10);         $client-&gt;send($request, $response);          return $response;     } } <\/code><\/pre>\n<p>  Provider \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 AuthenticationProviderInterface \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"php\">&lt;?php  namespace DG\\JiraAuthBundle\\Security\\Authentication\\Provider;  use DG\\JiraAuthBundle\\Entity\\User; use DG\\JiraAuthBundle\\Jira\\JiraRest; use DG\\JiraAuthBundle\\Security\\Authentication\\Token\\JiraToken; use Symfony\\Component\\Security\\Core\\Authentication\\Provider\\AuthenticationProviderInterface; use Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface; use Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException; use Symfony\\Component\\Security\\Core\\User\\UserProviderInterface;  class JiraProvider implements AuthenticationProviderInterface {      private $userProvider;     private $jiraRest;      public function __construct(UserProviderInterface $userProvider, $providerKey, JiraRest $jiraRest)     {         $this-&gt;userProvider = $userProvider;         $this-&gt;jiraRest = $jiraRest;     }      public function supports(TokenInterface $token)     {         return $token instanceof JiraToken;     }      public function authenticate(TokenInterface $token)     {         $user = $this-&gt;checkUserAuthentication($token);         $token-&gt;setUser($user);          return $token;     }      public function checkUserAuthentication(JiraToken $token){         $response = $this-&gt;jiraRest-&gt;getUserInfo($token-&gt;getJiraLogin(), $token-&gt;getJiraPassword());         if(!in_array('HTTP\/1.1 200 OK', $response-&gt;getHeaders())){             throw new AuthenticationException( 'Incorrect email and\/or password' );         }         $userInfo = json_decode($response-&gt;getContent());         $user = new User();         $user-&gt;setUsername($userInfo-&gt;name);         $user-&gt;setBase64Hash(base64_encode($token-&gt;getJiraLogin() . ':' . $token-&gt;getJiraPassword()));         $user-&gt;setEmail($userInfo-&gt;emailAddress);         $user-&gt;addRole('ROLE_USER');         return $user;     } } <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 User. \u042d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b Doctrine \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0430 \u043b\u0438\u0448\u043d\u044e\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0438\u0437 Jira, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0441\u0442\u0440\u0430\u0445\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u043e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0430. \u041f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u201c\u0441\u0442\u0440\u0430\u0445\u043e\u0432\u043a\u0430\u201d \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u0441\u0442\u0430\u0442\u044c\u0438, \u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u0430.<\/p>\n<h4>\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435<\/h4>\n<p>  \u0421\u0438\u0441\u0442\u0435\u043c\u0430 Security \u0432\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 Jira, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430. \u041c\u043e\u0436\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u044b \u043e\u0442 Jira, \u043d\u043e \u043f\u043e\u043a\u0430 \u044d\u0442\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0432 \u0440\u0430\u0441\u0441\u0447\u0435\u0442. \u041a\u043e\u0434 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<pre><code class=\"php\">&lt;?php  namespace DG\\JiraAuthBundle\\User;   use DG\\JiraAuthBundle\\Entity\\User; use DG\\JiraAuthBundle\\Jira\\JiraRest; use Symfony\\Component\\HttpFoundation\\Request; use Symfony\\Component\\HttpFoundation\\Session\\Session; use Symfony\\Component\\Security\\Core\\Exception\\UnsupportedUserException; use Symfony\\Component\\Security\\Core\\Exception\\UsernameNotFoundException; use Symfony\\Component\\Security\\Core\\User\\UserInterface; use Symfony\\Component\\Security\\Core\\User\\UserProviderInterface; use Symfony\\Component\\Security\\Core\\SecurityContextInterface;  class JiraUserProvider implements UserProviderInterface {      private $jiraRest;      public function __construct(JiraRest $jiraRest){         $this-&gt;jiraRest = $jiraRest;     }      public function loadUserByUsername($username)     {     }      public function refreshUser(UserInterface $user)     {         if (!$user instanceof User) {             throw new UnsupportedUserException(sprintf('Instances of &quot;%s&quot; are not supported.', get_class($user)));         }          $decodedUserData = base64_decode($user-&gt;getBase64Hash());         list($username, $password) = explode(':', $decodedUserData);         $userInfoResponse = $this-&gt;jiraRest-&gt;getUserInfo($username, $password);         $userInfo = json_decode($userInfoResponse-&gt;getContent());          $user = new User();         $user-&gt;setUsername($user-&gt;getUsername());         $user-&gt;setEmail($userInfo-&gt;emailAddress);         $user-&gt;setBase64Hash($user-&gt;getBase64Hash());         $user-&gt;addRole('ROLE_USER');         return $user;     }      public function supportsClass($class)     {         return $class === 'DG\\JiraAuthBundle\\Entity\\User';     } } <\/code><\/pre>\n<h4>\u0417\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p>  \u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0445 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u0438\u043c\u0435\u0440 services.yml \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043d\u0438\u0436\u0435. \u041e\u0442\u043c\u0435\u0447\u0443, \u0447\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 jira_url \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0432 parameters.yml \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c url \u0430\u0434\u0440\u0435\u0441 \u0434\u043e Jira.   <\/p>\n<pre><code class=\"python\">parameters:     dg_jira_auth.user_provider.class: DG\\JiraAuthBundle\\User\\JiraUserProvider     dg_jira_auth.listener.class: DG\\JiraAuthBundle\\Security\\Firewall\\JiraListener     dg_jira_auth.provider.class: DG\\JiraAuthBundle\\Security\\Authentication\\Provider\\JiraProvider     dg_jira_auth.handler.class: DG\\JiraAuthBundle\\Security\\Authentication\\Handler\\JiraAuthenticationHandler     dg_jira.rest.class: DG\\JiraAuthBundle\\Jira\\JiraRest  services:     dg_jira.rest:         class: %dg_jira.rest.class%         arguments:             - '%jira_url%'      dg_jira_auth.user_provider:         class: %dg_jira_auth.user_provider.class%         arguments:             - @dg_jira.rest      dg_jira_auth.authentication_success_handler:         class: %dg_jira_auth.handler.class%      dg_jira_auth.authentication_failure_handler:         class: %dg_jira_auth.handler.class%      dg_jira_auth.authentication_provider:         class: %dg_jira_auth.provider.class%         arguments: [@dg_jira_auth.user_provider, '', @dg_jira.rest]      dg_jira_auth.authentication_listener:         class: %dg_jira_auth.listener.class%         arguments:             - @security.context             - @security.authentication.manager             - @security.authentication.session_strategy             - @security.http_utils             - ''             - @dg_jira_auth.authentication_success_handler             - @dg_jira_auth.authentication_failure_handler             - ''             - @logger             - @event_dispatcher <\/code><\/pre>\n<h4>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 Symfony<\/h4>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0444\u0430\u0431\u0440\u0438\u043a\u0438 \u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0432 \u0431\u0430\u043d\u0434\u043b\u0435. <\/p>\n<pre><code class=\"php\">&lt;?php  namespace DG\\JiraAuthBundle\\DependencyInjection\\Security\\Factory;  use Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AbstractFactory; use Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition; use Symfony\\Component\\DependencyInjection\\ContainerBuilder; use Symfony\\Component\\DependencyInjection\\DefinitionDecorator; use Symfony\\Component\\DependencyInjection\\Reference;  class JiraFactory extends AbstractFactory {      public function __construct(){         $this-&gt;addOption('username_parameter', '_username');         $this-&gt;addOption('password_parameter', '_password');         $this-&gt;addOption('intention', 'authenticate');         $this-&gt;addOption('post_only', true);     }      protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId)     {         $provider = 'dg_jira_auth.authentication_provider.'.$id;         $container             -&gt;setDefinition($provider, new DefinitionDecorator('dg_jira_auth.authentication_provider'))             -&gt;replaceArgument(1, $id)         ;          return $provider;     }      protected function getListenerId()     {         return 'dg_jira_auth.authentication_listener';     }      public function getPosition()     {         return 'form';     }      public function getKey()     {         return 'jira-form';     }      protected function createListener($container, $id, $config, $userProvider)     {         $listenerId = parent::createListener($container, $id, $config, $userProvider);          if (isset($config['csrf_provider'])) {             $container                 -&gt;getDefinition($listenerId)                 -&gt;addArgument(new Reference($config['csrf_provider']))             ;         }          return $listenerId;     }      protected function createEntryPoint($container, $id, $config, $defaultEntryPoint)     {         $entryPointId = 'security.authentication.form_entry_point.'.$id;         $container             -&gt;setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))             -&gt;addArgument(new Reference('security.http_utils'))             -&gt;addArgument($config['login_path'])             -&gt;addArgument($config['use_forward'])         ;          return $entryPointId;     } } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 \u0431\u0430\u043d\u0434\u043b\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432 \u043c\u0435\u0442\u043e\u0434 build \u0443 \u043a\u043b\u0430\u0441\u0441\u0430 \u0431\u0430\u043d\u0434\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443<\/p>\n<pre><code class=\"php\">$extension-&gt;addSecurityListenerFactory(new JiraFactory()); <\/code><\/pre>\n<h4>\u041e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435<\/h4>\n<p>  \u0412\u0441\u0435, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Jira. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 JiraUserProvider \u0432 security.yml \u0432 \u0441\u0435\u043a\u0446\u0438\u044e providers \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a<\/p>\n<pre><code class=\"python\">        jira_auth_provider:             id: dg_jira_auth.user_provider <\/code><\/pre>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 firewalls \u043d\u043e\u0432\u0443\u044e \u0441\u0435\u043a\u0446\u0438\u044e, \u043f\u043e\u043b\u0430\u0433\u0430\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430\u0434\u0440\u0435\u0441\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0441 \/jira\/ \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0437\u0430\u043a\u0440\u044b\u0442\u044b \u043e\u0442 \u043d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439:<\/p>\n<pre><code class=\"python\">    jira_secured:         provider:               jira_auth_provider         switch_user:            false         context:                user         pattern:                \/jira\/.*         jira_form:             check_path:         dg_jira_auth_check_path             login_path:         dg_jira_auth_login_path             default_target_path: dg_jira_auth_private         logout:             path:               dg_jira_auth_logout             target:             dg_jira_auth_public         anonymous:              true <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0442\u0440\u0438\u0445 \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u043a \u0432 \u0441\u0435\u043a\u0446\u0438\u044e access_controls, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0445 \u0440\u043e\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u044b\u0439 \u0432\u0438\u0434 \u0441\u0442\u0440\u043e\u043a \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0435\u0442 \u0432\u0438\u0434<\/p>\n<pre><code class=\"python\">- { path: ^\/jira\/public, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^\/jira\/private\/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^\/jira\/private(.*)$, role: ROLE_USER } <\/code><\/pre>\n<h4>PS<\/h4>\n<p>  \u0412\u0435\u0441\u044c \u043a\u043e\u0434, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435, \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u0431\u0430\u043d\u0434\u043b\u0430 \u0438\u0437 \u043f\u0430\u043a\u0435\u0442\u0430 \u00abdg\/jira-auth-bundle\u00bb \u0432 composer. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0430\u043d\u0434\u043b\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 AppKernel.php \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u043a\u0446\u0438\u044e<\/p>\n<pre><code class=\"python\">_jira_auth:     resource: &quot;@DGJiraAuthBundle\/Resources\/config\/routing.yml&quot;     prefix:   \/jira\/ <\/code><\/pre>\n<p>  \u0432 routing.yml. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0439\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \/jira\/public \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Jira.<\/p>\n<h4>\u0414\u043b\u044f \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430<\/h4>\n<p>  \u0412 Symfony Cookbook \u0435\u0441\u0442\u044c \u0442\u0430\u043a \u0436\u0435 <a href=\"http:\/\/symfony.com\/doc\/current\/cookbook\/security\/custom_authentication_provider.html\">\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f<\/a>, \u043a\u0430\u043a \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u0432\u0435\u0431 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<p>  <b>\u041d\u0430\u0434\u0435\u044e\u0441\u044c \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u0430\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u0430!<\/b> \t\t\t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/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=\"http:\/\/habrahabr.ru\/post\/206888\/\"> http:\/\/habrahabr.ru\/post\/206888\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435, \u0425\u0430\u0431\u0440\u043e\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Symfony2 \u0438 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 Jira.<\/p>\n<h4>\u0417\u0430\u0447\u0435\u043c \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c Jira \u0438 Symfony2?<\/h4>\n<p>  \u0412 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0433\u0434\u0435 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0441\u0430\u043f\u043f\u043e\u0440\u0442\u0430 \u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u0437\u0430\u0434\u0430\u0447 \u0447\u0435\u0440\u0435\u0437 API, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u044f\u0432\u043a\u0438 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b\u0442\u044c \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u044b \u0432 \u0442\u0438\u043a\u0435\u0442\u044b. \u041f\u0435\u0440\u0432\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u0441\u0442\u0430\u043b\u0430 \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u043f\u0443\u0442\u0438, \u0431\u044b\u043b\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Jira (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u201cBasic Authentication\u201d) \u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 Symfony2. \u0414\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439: <a href=\"http:\/\/symfony.com\/doc\/current\/book\/security.html\">http:\/\/symfony.com\/doc\/current\/book\/security.html<\/a>.  <\/p>\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-206888","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/206888","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=206888"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/206888\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=206888"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=206888"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=206888"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}