Hindi (हिंदी) translation by Ashish Rampal (you can also view the original English article)
इस आर्टिकल में, आप सीखेंगे कि Symfony सिक्योरिटी कंपोनेंट्स का उपयोग करके PHP में यूजर ऑथेंटिकेशन कैसे सेट अप करें। साथ ही साथ ऑथेंटिकेशन, मैं आपको दिखाऊंगा कि इसकी रोल-बेस्ड ऑथॉरिज़ेशन का उपयोग कैसे करें, जिसे आप अपनी आवश्यकताओं के अनुसार बढ़ा सकते हैं।
Symfony सिक्योरिटी कंपोनेंट्स
Symfony सिक्योरिटी कंपोनेंट्स आपको सुरक्षा फीचर्स ऑथेंटिकेशन, रोल-बेस्ड ऑथॉरिज़ेशन, CSRF टोकन और भी बहुत कुछ आसानी से को सेटअप करने की अनुमति देता है। वास्तव में, इसे आगे चार सब-कंपोनेंट्स में विभाजित किया गया है जिन्हें आप अपनी आवश्यकताओं के अनुसार चुन सकते हैं।
सिक्योरिटी कंपोनेंट्स में निम्नलिखित सब-कंपोनेंट्स हैं:
- symfony/security-core
- symfony/security-http
- symfony/security-csrf
- symfony/security-acl
इस आर्टिकल में, हम symfony/security-core कॉम्पोनेन्ट द्वारा प्रदान किये गए ऑथेंटिकेशन फीचर का पता लगाने जा रहे हैं।
हमेशा की तरह, हम इंस्टालेशन और कॉन्फ़िगरेशन निर्देशों से शुरू करेंगे, और फिर हम महत्वपूर्ण कांसेप्ट को प्रदर्शित करने के लिए कुछ वास्तविक-दुनिया के उदाहरणों से पता लगाएंगे।
इंस्टालेशन और कॉन्फ़िगरेशन
इस सेक्शन में, हम Symfony सिक्योरिटी कॉम्पोनेन्ट इनस्टॉल करने जा रहे हैं। मुझे लगता है कि आपने पहले से ही अपने सिस्टम पर कंपोजर इनस्टॉल कर लिया है-हमें इसे Packagist पर उपलब्ध सिक्योरिटी कॉम्पोनेन्ट इनस्टॉल करने की आवश्यकता होगी।
तो आगे बढ़ें और निम्न कमांड का उपयोग कर सिक्योरिटी कॉम्पोनेन्ट इनस्टॉल करें।
$composer require symfony/security
हम यूज़र्स को हमारे उदाहरण में MySQL डेटाबेस से लोड करने जा रहे हैं, इसलिए हमें डेटाबेस एब्स्ट्रक्शन लेयर की भी आवश्यकता होगी। आइए सबसे लोकप्रिय डेटाबेस अब्स्ट्रक्शन लेयर्स में से एक इनस्टॉल करें: Doctrine DBAL।
$composer require doctrine/dbal
उसने composer.json फ़ाइल बनाई होनी चाहिए, जो इस तरह दिखना चाहिए:
{ "require": { "symfony/security": "^4.1", "doctrine/dbal": "^2.7" } }
आइए निम्न की तरह दिखने के लिए composer.json फ़ाइल को संशोधित करें।
{ "require": { "symfony/security": "^4.1", "doctrine/dbal": "^2.7" }, "autoload": { "psr-4": { "Sfauth\\": "src" }, "classmap": ["src"] } }
चूंकि हमने एक नई classmap
एंट्री जोड़ दी है, चलिए आगे बढ़ें और निम्न कमांड चलाकर कंपोजर ऑटोलोडर अपडेट करें।
$composer dump -o
अब, आप src डायरेक्टरी के अंदर क्लासेज को ऑटोलोड करने के लिए Sfauth
नेमस्पेस का उपयोग कर सकते हैं।
तो यह इंस्टालेशन का हिस्सा है, लेकिन आप इसका उपयोग कैसे कर रहे हैं? वास्तव में, यह आपके एप्लीकेशन में कंपोजर द्वारा बनाई गई autoload.php फ़ाइल को शामिल करने का विषय है, जैसा कि निम्न स्निपेट में दिखाया गया है।
<?php require_once './vendor/autoload.php'; // application code ?>
एक असली दुनिया का उदाहरण
सबसे पहले, Symfony सिक्योरिटी कॉम्पोनेन्ट द्वारा प्रदान किए गए सामान्य ऑथेंटिकेशन फ्लो के माध्यम से चलो।
- पहली बात यह है कि यूजर क्रेडेंशियल को रिट्रीव करें और एक अन ऑथेंटिकेटेड टोकन बनाएं।
- इसके बाद, हम वेलिडेशन के लिए ऑथेंटिकेशन मैनेजर को एक अन ऑथेंटिकेटेड टोकन पास करेंगे।
- ऑथेंटिकेशन मैनेजर में विभिन्न ऑथेंटिकेशन प्रोवाइडर्स हो सकते हैं, और उनमें से एक का उपयोग वर्तमान यूजर रिक्वेस्ट को ऑथेंटिकेटेड करने के लिए किया जाएगा। यूजर को ऑथेंटिकेटेड कैसे किया जाता है इसका लॉजिक ऑथेंटिकेशन प्रोवाइडर में परिभाषित किया गया है।
- ऑथेंटिकेशन प्रोवाइडर यूजर प्रोवाइडर को यूजर को रिट्रीव करने के लिए कांटेक्ट करता है। यूज़र्स को संबंधित बैक-एंड से लोड करने के लिए यूजर प्रोवाइडर की ज़िम्मेदारी है।
- यूजर प्रोवाइडर ऑथेंटिकेशन प्रोवाइडर द्वारा प्रदान किए गए क्रेडेंशियल प्रोवाइडर का उपयोग कर यूजर को लोड करने का प्रयास करता है। ज्यादातर मामलों में, यूजर प्रोवाइडर यूजर ऑब्जेक्ट रीटर्न करता है जो
UserInterface
इंटरफ़ेस को इम्प्लीमेंट करता है। - यदि यूजर मिल जाता है, ऑथेंटिकेशन प्रोवाइडर एक अन ऑथेंटिकेटेड टोकन देता है, और आप बाद के रिक्वेस्ट्स के लिए इस टोकन को स्टोर कर सकते हैं।
हमारे उदाहरण में, हम MySQL डेटाबेस के विरुद्ध यूजर क्रेडेंशियल से मेल खाते हैं, इस प्रकार हमें डेटाबेस यूजर प्रोवाइडर बनाने की आवश्यकता होगी। हम डेटाबेस ऑथेंटिकेशन प्रोवाइडर भी बनाएंगे जो ऑथेंटिकेशन लॉजिक को संभालता है। और अंत में, हम यूजर क्लास बनाएंगे, जो UserInterface
इंटरफ़ेस को इम्प्लीमेंट करती है।
User क्लास
इस सेक्शन में, हम User क्लास बनाएंगे जो ऑथेंटिकेशन प्रक्रिया में यूजर एंटिटी का प्रतिनिधित्व करती है।
आगे बढ़ें और निम्नलिखित कंटेंट के साथ src/User/User.php फ़ाइल बनाएं।
<?php namespace Sfauth\User; use Symfony\Component\Security\Core\User\UserInterface; class User implements UserInterface { private $username; private $password; private $roles; public function __construct(string $username, string $password, string $roles) { if (empty($username)) { throw new \InvalidArgumentException('No username provided.'); } $this->username = $username; $this->password = $password; $this->roles = $roles; } public function getUsername() { return $this->username; } public function getPassword() { return $this->password; } public function getRoles() { return explode(",", $this->roles); } public function getSalt() { return ''; } public function eraseCredentials() {} }
महत्वपूर्ण बात यह है कि यूजर क्लास को Symfony सिक्योरिटी UserInterface
इंटरफेस को लागू करना होगा। इसके अलावा, यहां साधारण कुछ भी नहीं है।
डेटाबेस प्रोवाइडर क्लास
यूज़र्स को बैक-एंड से लोड करना यूजर प्रोवाइडर की ज़िम्मेदारी है। इस सेक्शन में, हम डेटाबेस यूजर प्रोवाइडर बनाएंगे, जो यूजर को MySQL डेटाबेस से लोड करता है।
आइए निम्नलिखित कंटेंट के साथ src/User/DatabaseUserProvider.php फ़ाइल बनाएं।
<?php namespace Sfauth\User; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Doctrine\DBAL\Connection; use Sfauth\User\User; class DatabaseUserProvider implements UserProviderInterface { private $connection; public function __construct(Connection $connection) { $this->connection = $connection; } public function loadUserByUsername($username) { return $this->getUser($username); } private function getUser($username) { $sql = "SELECT * FROM sf_users WHERE username = :name"; $stmt = $this->connection->prepare($sql); $stmt->bindValue("name", $username); $stmt->execute(); $row = $stmt->fetch(); if (!$row['username']) { $exception = new UsernameNotFoundException(sprintf('Username "%s" not found in the database.', $row['username'])); $exception->setUsername($username); throw $exception; } else { return new User($row['username'], $row['password'], $row['roles']); } } public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } return $this->getUser($user->getUsername()); } public function supportsClass($class) { return 'Sfauth\User\User' === $class; } }
यूजर प्रोवाइडर को UserProviderInterface
इंटरफ़ेस को लागू करना होगा। हम डेटाबेस से संबंधित संचालन करने के लिए doctrine DBAL का उपयोग कर रहे हैं। चूंकि हमने UserProviderInterface
इंटरफ़ेस को इम्प्लीमेंट किया है, हमें loadUserByUsername
, refreshUser
, और supportClass
मेथड्स को इम्प्लीमेंट करना ही होगा।
loadUserByUsername
मेथड को यूजर को यूजरनेम से लोड करना चाहिए, और यह getUser
मेथड में किया गया है। यदि यूजर मिल जाता है, तो हम संबंधित Sfauth\User\User
ऑब्जेक्ट को रीटर्न करते हैं, जो UserInterface
इंटरफ़ेस को लागू करता है।
दूसरी ओर, refreshUser
मेथड डेटाबेस से लेटेस्ट जानकारी प्राप्त करके आपूर्ति किए गए User
ऑब्जेक्ट को रीफ्रेश करता है।
और अंत में, supportClass
मेथड जांचता है कि क्या DatabaseUserProvider
प्रोवाइडर सप्लाई किए गए यूजर क्लास को सपोर्ट करता है।
डेटाबेस ऑथेंटिकेशन प्रोवाइडर क्लास
अंत में, हमें यूजर ऑथेंटिकेशन प्रोवाइडर को इम्प्लीमेंट करने की आवश्यकता है, जो ऑथेंटिकेशन लॉजिक को परिभाषित करता है-यूजर को ऑथेंटिकेट कैसे किया जाता है। हमारे मामले में, हमें MySQL डेटाबेस के विरुद्ध यूजर क्रेडेंशियल से मिलान करने की आवश्यकता है, और इस प्रकार हमें ऑथेंटिकेशन लॉजिक को तदनुसार परिभाषित करने की आवश्यकता है।
आगे बढ़ें और निम्नलिखित कंटेंट के साथ src/user/DatabaseAuthenticationProvider.php फ़ाइल को बनाएं।
<?php namespace Sfauth\User; use Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; class DatabaseAuthenticationProvider extends UserAuthenticationProvider { private $userProvider; public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, string $providerKey, bool $hideUserNotFoundExceptions = true) { parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions); $this->userProvider = $userProvider; } protected function retrieveUser($username, UsernamePasswordToken $token) { $user = $token->getUser(); if ($user instanceof UserInterface) { return $user; } try { $user = $this->userProvider->loadUserByUsername($username); if (!$user instanceof UserInterface) { throw new AuthenticationServiceException('The user provider must return a UserInterface object.'); } return $user; } catch (UsernameNotFoundException $e) { $e->setUsername($username); throw $e; } catch (\Exception $e) { $e = new AuthenticationServiceException($e->getMessage(), 0, $e); $e->setToken($token); throw $e; } } protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token) { $currentUser = $token->getUser(); if ($currentUser instanceof UserInterface) { if ($currentUser->getPassword() !== $user->getPassword()) { throw new AuthenticationException('Credentials were changed from another session.'); } } else { $password = $token->getCredentials(); if (empty($password)) { throw new AuthenticationException('Password can not be empty.'); } if ($user->getPassword() != md5($password)) { throw new AuthenticationException('Password is invalid.'); } } } }
DatabaseAuthenticationProvider
ऑथेंटिकेशन प्रोवाइडर UserAuthenticationProvider
अब्स्ट्रक्ट क्लास को एक्सटेंड करता है। इसलिए, हमें retrieveUser
को और checkAuthentication
अब्स्ट्रक्ट मेथड्स को इम्प्लीमेंट करने की आवश्यकता है।
retrieveUser
मेथड का काम यूजर को संबंधित यूजर प्रोवाइडर से लोड करना है। हमारे मामले में, यह UserUserProvider
यूजर प्रोवाइडर का उपयोग यूजर को MySQL डेटाबेस से लोड करने के लिए करेगा।
दूसरी ओर, वर्तमान यूजर ऑथेंटिकेटेड करने के लिए checkAuthentication
मेथड आवश्यक जांच करता है। कृपया ध्यान दें कि मैंने पासवर्ड एन्क्रिप्शन के लिए MD5 मेथड का उपयोग किया है। बेशक, आपको यूजर पासवर्ड स्टोर करने के लिए अधिक सुरक्षित एन्क्रिप्शन मेथड्स का उपयोग करना चाहिए।
यह कैसे काम करता है
अब तक, हमने ऑथेंटिकेशन के लिए सभी आवश्यक एलिमेंट बनाए हैं। इस सेक्शन में, हम देखेंगे कि ऑथेंटिकेशन फंक्शनलिटी सेट अप करने के लिए इसे सभी कैसे एक साथ रखा जाए।
आगे बढ़ें और db_auth.php फ़ाइल बनाएं और इसे निम्न कंटेंट के साथ पॉप्युलेट करें।
<?php require_once './vendor/autoload.php'; use Sfauth\User\DatabaseUserProvider; use Symfony\Component\Security\Core\User\UserChecker; use Sfauth\User\DatabaseAuthenticationProvider; use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; // init doctrine db connection $doctrineConnection = \Doctrine\DBAL\DriverManager::getConnection( array('url' => 'mysql://{USERNAME}:{PASSWORD}@{HOSTNAME}/{DATABASE_NAME}'), new \Doctrine\DBAL\Configuration() ); // init our custom db user provider $userProvider = new DatabaseUserProvider($doctrineConnection); // we'll use default UserChecker, it's used to check additional checks like account lock/expired etc. // you can implement your own by implementing UserCheckerInterface interface $userChecker = new UserChecker(); // init our custom db authentication provider $dbProvider = new DatabaseAuthenticationProvider( $userProvider, $userChecker, 'frontend' ); // init authentication provider manager $authenticationManager = new AuthenticationProviderManager(array($dbProvider)); try { // init un/pw, usually you'll get these from the $_POST variable, submitted by the end user $username = 'admin'; $password = 'admin'; // get unauthenticated token $unauthenticatedToken = new UsernamePasswordToken( $username, $password, 'frontend' ); // authenticate user & get authenticated token $authenticatedToken = $authenticationManager->authenticate($unauthenticatedToken); // we have got the authenticated token (user is logged in now), it can be stored in a session for later use echo $authenticatedToken; echo "\n"; } catch (AuthenticationException $e) { echo $e->getMessage(); echo "\n"; }
इस आर्टिकल की शुरुआत में चर्चा की गई ऑथेंटिकेशन फ्लो को याद करें- उपर्युक्त कोड उस सीक्वेंस को दर्शाता है।
पहली बात यह थी कि यूजर क्रेडेंशियल रिट्रीव करें और एक अन ऑथेंटिकेटेड टोकन बनाएं।
$unauthenticatedToken = new UsernamePasswordToken( $username, $password, 'frontend' );
इसके बाद, हमने वेलिडेशन के लिए ऑथेंटिकेशन मैनेजर को उस टोकन को पास कर दिया है।
// authenticate user & get authenticated token $authenticatedToken = $authenticationManager->authenticate($unauthenticatedToken);
जब ऑथेंटिकेशन मेथड कॉल किया जाता है, तो सीन के पीछे बहुत सी चीजें हो रही हैं।
सबसे पहले, ऑथेंटिकेशन मैनेजर एक उपयुक्त ऑथेंटिकेशन प्रोवाइडर का चयन करता है। हमारे मामले में, यह DatabaseAuthenticationProvider
ऑथेंटिकेशन प्रोवाइडर है, जिसे ऑथेंटिकेशन के लिए चुना जाएगा।
इसके बाद, यह यूजर को DatabaseUserProvider
यूजर प्रोवाइडर से यूजरनेम से रिट्रीव करता है। अंत में, checkAuthentication
मेथड वर्तमान यूजर रिक्वेस्ट को ऑथेंटिकेट करने के लिए आवश्यक चेक करता है।
क्या आप db_auth.php स्क्रिप्ट का परीक्षण करना चाहते हैं, तो आपको अपने MySQL डेटाबेस में sf_users
टेबल बनाने की आवश्यकता होगी।
CREATE TABLE `sf_users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `roles` enum('registered','moderator','admin') DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; INSERT INTO `sf_users` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3','admin');
आगे बढ़ें और यह देखने के लिए db_auth.php स्क्रिप्ट चलाएं कि यह कैसा चल रहा है। सफल समापन पर, आपको निम्न स्निपेट में दिखाए गए अनुसार एक ऑथेंटिकेटेड टोकन प्राप्त होना चाहिए।
$php db_auth.php UsernamePasswordToken(user="admin", authenticated=true, roles="admin")
एक बार यूजर के ऑथेंटिकेट हो जाने के बाद, आप बाद के रिक्वेस्ट्स के लिए सेशन में ऑथेंटिकेटेड टोकन स्टोर कर सकते हैं।
और उसके साथ, हमने अपना सरल ऑथेंटिकेशन डेमो पूरा कर लिया है!
निष्कर्ष
आज, हमने Symfony सिक्योरिटी कंपोनेंट्स को देखा, जो आपको अपने PHP ऍप्लिकेशन्स में सिक्योरिटी फीचर्स को इंटेग्रेट करने की अनुमति देता है। विशेष रूप से, हमने symfony/security-core सब-कॉम्पोनेन्ट द्वारा प्रदान किये गए ऑथेंटिकेशन फीचर पर चर्चा की, और मैंने आपको एक उदाहरण दिखाया कि इस फंक्शनलिटी को आपके स्वयं के ऐप में कैसे इम्प्लीमेंट किया जा सकता है।
नीचे दिए गए फ़ीड का उपयोग करके अपने विचार पोस्ट करने के लिए स्वतंत्र महसूस करें!