हेलो, हैबरोसिटी। इस लेख में मैं बात करना चाहता हूं कि आप जाने-माने सिम्फनी 2 ढांचे और कम प्रसिद्ध जीरा ट्रैकर के साथ कैसे दोस्त बना सकते हैं।
जीरा और सिम्फनी 2 क्यों बांधें?
जिस कंपनी में मैं काम करता हूं, वहां एपीआई के जरिए सपोर्ट सिस्टम और टास्क ट्रैकर को जोड़ने की जरूरत थी ताकि ग्राहकों से अनुरोधों को आसानी से टिकट में बदला जा सके। प्राथमिक समस्या जो हमारे रास्ते में खड़ी थी, जीरा प्रमाणीकरण (मूल प्रमाणीकरण तंत्र का उपयोग करके) और सिम्फनी 2 सुरक्षा प्रणाली का एकीकरण था। प्रमाणीकरण तंत्र और प्राधिकरण ढांचे को समझने के लिए, आपको आधिकारिक दस्तावेज के साथ खुद को परिचित करना होगा:
http://symfony.com/doc/current/book/security.html ।
Symfony2 में आपको एक नया प्राधिकरण प्रकार बनाने की आवश्यकता क्या है?
- टोकन, जो प्रमाणीकरण के दौरान उपयोगकर्ता द्वारा दर्ज की गई जानकारी संग्रहीत करेगा।
- उपयोगकर्ता प्राधिकरण को सत्यापित करने के लिए श्रोता की आवश्यकता है।
- प्रदाता सीधे जीरा के माध्यम से प्रमाणीकरण को लागू कर रहा है।
- उपयोगकर्ता प्रदाता जो Symfony2 Security उपयोगकर्ता की जानकारी के लिए क्वेरी करेगा।
- फैक्टरी, जो एक नया प्रमाणीकरण और प्राधिकरण विधि पंजीकृत करेगी।
टोकन बनाएँ
सिम्फनी उपयोगकर्ता प्रमाणीकरण के दौरान दर्ज की गई जानकारी को बचाने और बाद में इसका उपयोग करने के लिए AbstractToken वर्ग से प्राप्त टोकन का उपयोग करती है। विचाराधीन समस्या में, 2 फ़ील्ड स्टोर करना आवश्यक है - यह उपयोगकर्ता का उपयोगकर्ता नाम और पासवर्ड है, जिसके आधार पर प्राधिकरण को जीरा में जांचा जाएगा। टोकन क्लास कार्यान्वयन कोड नीचे दिया गया है।
<?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->setAuthenticated(count($roles) > 0); } public function getJiraLogin(){ return $this->jira_login; } public function setJiraLogin($jira_login){ $this->jira_login = $jira_login; } public function getJiraPassword(){ return $this->jira_password; } public function setJiraPassword($jira_password){ $this->jira_password = $jira_password; } public function serialize() { return serialize(array($this->jira_login, $this->jira_password, parent::serialize())); } public function unserialize($serialized) { list($this->jira_login, $this->jira_password, $parent_data) = unserialize($serialized); parent::unserialize($parent_data); } public function getCredentials(){ return ''; } }
श्रोता कार्यान्वयन
अब जब हमने उपयोगकर्ता डेटा संग्रहीत कर लिया है, तो शुद्धता की जांच करना संभव होना चाहिए। यदि डेटा पुराना हो गया है, तो आपको इस बारे में रूपरेखा को सूचित करना होगा। ऐसा करने के लिए, आपको AbstractAuthenticationListener से विरासत में मिली श्रोता को लागू करना होगा।
<?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->options['post_only'] && 'post' !== strtolower($request->getMethod())) { if (null !== $this->logger) { $this->logger->debug(sprintf('Authentication method not supported: %s.', $request->getMethod())); } return null; } $username = trim($request->get($this->options['username_parameter'], null, true)); $password = $request->get($this->options['password_parameter'], null, true); $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username); $request->getSession()->set('jira_auth', base64_encode($username.':'.$password)); $token = new JiraToken(); $token->setJiraLogin($username); $token->setJiraPassword($password); return $this->authenticationManager->authenticate($token); } }
जीरा में प्राधिकरण। प्रदाता
सबसे महत्वपूर्ण बात के लिए समय आ गया है - सीधे जीरा को डेटा भेजना। बाकी एपी ट्रैकर के साथ काम करने के लिए, एक साधारण वर्ग लिखा जाता है जो एक सेवा के रूप में जोड़ता है। जीरा एपीआई के साथ काम करने के लिए, बज़ लाइब्रेरी का उपयोग किया जाता है।
<?php namespace DG\JiraAuthBundle\Jira; use Buzz\Message; use Buzz\Client\Curl; class JiraRest { private $jiraUrl = ''; public function __construct($jiraUrl){ $this->jiraUrl = $jiraUrl; } public function getUserInfo($username, $password){ $request = new Message\Request( 'GET', '/rest/api/2/user?username=' . $username, $this->jiraUrl ); $request->addHeader('Authorization: Basic ' . base64_encode($username . ':' . $password) ); $request->addHeader('Content-Type: application/json'); $response = new Message\Response(); $client = new Curl(); $client->setTimeout(10); $client->send($request, $response); return $response; } }
प्रदाता को AuthenticationProviderInterface इंटरफ़ेस लागू करना चाहिए और इस तरह दिखता है:
<?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->userProvider = $userProvider; $this->jiraRest = $jiraRest; } public function supports(TokenInterface $token) { return $token instanceof JiraToken; } public function authenticate(TokenInterface $token) { $user = $this->checkUserAuthentication($token); $token->setUser($user); return $token; } public function checkUserAuthentication(JiraToken $token){ $response = $this->jiraRest->getUserInfo($token->getJiraLogin(), $token->getJiraPassword()); if(!in_array('HTTP/1.1 200 OK', $response->getHeaders())){ throw new AuthenticationException( 'Incorrect email and/or password' ); } $userInfo = json_decode($response->getContent()); $user = new User(); $user->setUsername($userInfo->name); $user->setBase64Hash(base64_encode($token->getJiraLogin() . ':' . $token->getJiraPassword())); $user->setEmail($userInfo->emailAddress); $user->addRole('ROLE_USER'); return $user; } }
जैसा कि आप कार्यान्वयन से देख सकते हैं, उपयोगकर्ता डेटा उपयोगकर्ता इकाई में संग्रहीत है। ऐसा इसलिए किया जा सकता है ताकि डॉक्ट्रिन डेटाबेस में एक अतिरिक्त तालिका न बनाए, लेकिन भविष्य में आप ट्रैकर की अस्थायी दुर्गमता से खुद को बचाने के लिए इस तालिका में जीरा से उपयोगकर्ताओं के बारे में जानकारी जोड़ सकते हैं। ऐसा "बीमा" लेख के दायरे से परे है, लेकिन बहुत उपयोगी हो सकता है।
अधिकृत उपयोगकर्ता जानकारी प्रदान करना
ढांचे में सुरक्षा प्रणाली उपयोगकर्ता की जानकारी के लिए प्राधिकरण को सत्यापित करने के लिए कहती है। यह स्पष्ट है कि ऐसी जानकारी जीरा में स्थित है, इसलिए हमें इसे ट्रैकर से प्राप्त करना चाहिए। आप निश्चित रूप से, जीरा से जवाब कैश कर सकते हैं, लेकिन अब हम इसे ध्यान में नहीं रखेंगे। प्रदाता कोड नीचे दिया गया है।
<?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->jiraRest = $jiraRest; } public function loadUserByUsername($username) { } public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } $decodedUserData = base64_decode($user->getBase64Hash()); list($username, $password) = explode(':', $decodedUserData); $userInfoResponse = $this->jiraRest->getUserInfo($username, $password); $userInfo = json_decode($userInfoResponse->getContent()); $user = new User(); $user->setUsername($user->getUsername()); $user->setEmail($userInfo->emailAddress); $user->setBase64Hash($user->getBase64Hash()); $user->addRole('ROLE_USER'); return $user; } public function supportsClass($class) { return $class === 'DG\JiraAuthBundle\Entity\User'; } }
कॉन्फ़िगरेशन भरना
निर्मित कक्षाओं का उपयोग करने के लिए, आपको उन्हें कॉन्फ़िगरेशन में सेवाओं के रूप में पंजीकृत करना होगा। नीचे सेवाओं की एक मिसाल दी गई है। मैं ध्यान देता हूं कि jira_url पैरामीटर को पैरामीटर में परिभाषित किया जाना चाहिए। Jira से पहले url पता होना चाहिए।
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
सिम्फनी में एक नया प्रमाणीकरण और प्राधिकरण विधि पंजीकृत करें
उपरोक्त सभी कार्यों के लिए, आपको एक कारखाने के रूप में प्रमाणीकरण व्यवहार का वर्णन करना होगा और इसे बंडल में पंजीकृत करना होगा।
<?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->addOption('username_parameter', '_username'); $this->addOption('password_parameter', '_password'); $this->addOption('intention', 'authenticate'); $this->addOption('post_only', true); } protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId) { $provider = 'dg_jira_auth.authentication_provider.'.$id; $container ->setDefinition($provider, new DefinitionDecorator('dg_jira_auth.authentication_provider')) ->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 ->getDefinition($listenerId) ->addArgument(new Reference($config['csrf_provider'])) ; } return $listenerId; } protected function createEntryPoint($container, $id, $config, $defaultEntryPoint) { $entryPointId = 'security.authentication.form_entry_point.'.$id; $container ->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point')) ->addArgument(new Reference('security.http_utils')) ->addArgument($config['login_path']) ->addArgument($config['use_forward']) ; return $entryPointId; } }
बंडल में पंजीकरण करने के लिए, आपको बंडल वर्ग के निर्माण की विधि में लाइन को जोड़ना होगा
$extension->addSecurityListenerFactory(new JiraFactory());
अंतिम परिचय
सब कुछ, अब हम जीरा के साथ काम का परीक्षण करने के लिए तैयार हैं। तार के रूप में प्रदाता अनुभाग में सुरक्षा में JiraUserProvider बनाया जोड़ें
jira_auth_provider: id: dg_jira_auth.user_provider
अगला, आपको फायरवॉल में एक नया खंड जोड़ने की जरूरत है, यह मानते हुए कि सभी पृष्ठ जिनके पते / जीरा के साथ शुरू होते हैं / अनधिकृत उपयोगकर्ताओं के लिए डिफ़ॉल्ट रूप से बंद हैं:
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
अंतिम स्पर्श एक्सेस_कंट्रोल अनुभाग में पंक्तियों को जोड़ रहा है जो पृष्ठों को देखने के लिए आवश्यक उपयोगकर्ता भूमिकाओं को परिभाषित करता है। लाइनों का अनुमानित रूप हो सकता है
- { path: ^/jira/public, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/jira/private/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/jira/private(.*)$, role: ROLE_USER }
पुनश्च
लेख के सभी कोड संगीतकार में या
github के साथ dg / jira-Cort-बंडल पैकेज से बंडल के रूप में स्थापित किए जा सकते हैं। काम करने के लिए बंडल के लिए, आपको इसे AppKernel.php में पंजीकृत करना होगा और एक अनुभाग जोड़ना होगा
_jira_auth: resource: "@DGJiraAuthBundle/Resources/config/routing.yml" prefix: /jira/
in routing.yml उसके बाद, आप पृष्ठ / जीरा / सार्वजनिक पर जा सकते हैं और जीरा के माध्यम से प्राधिकरण का परीक्षण कर सकते हैं।
सामग्री को सुरक्षित करने के लिए
सिम्फनी कुकबुक में थर्ड-पार्टी वेब सेवा के माध्यम से प्रमाणीकरण कैसे लागू किया जाए, इसके भी
निर्देश हैं ।
मुझे उम्मीद है कि लेख आपके लिए उपयोगी होगा!