2011-01-16 5 views
14

मैं एक छोटे से Doctrine2 समर्थित पहली बार के लिए Symfony2 का उपयोग कर परियोजना पर काम कर रहा हूँ में आधारित प्रमाणीकरण तंत्र। वर्तमान में मैं documentation में वर्णित प्रमाणीकरण तंत्र के साथ सटीक होने के लिए symfony2 के सुरक्षा घटक के साथ संघर्ष कर रहा हूं।सिद्धांत Symfony2 परियोजना

मैं एक रूप-आधारित प्रमाणीकरण का उपयोग करना चाहते हैं और सब कुछ था डॉक्स में कहा गया है:

security.config: 
    firewalls: 
     admin: 
      pattern:        /admin/.* 
      form-login:       true 
      logout:        true 
      login_path:       /login 
      check_path:       /validateLogin 
      always_use_default_target_path:  false 
      target_path_parameter:    target 
     check_page: 
      pattern:        /validateLogin 
      form-login:       true 
      login_path:       /login 
      check_path:       /validateLogin 
      always_use_default_target_path:  false 
      target_path_parameter:    target 
     public: 
      pattern:        /.* 
      security:       false 
    providers: 
     admin: 
      password_encoder:     md5 
      entity: 
       class:       AdminBundle:User 
       property:      username 
    access_control: 
     - { path: /admin/.*, role: ROLE_ADMIN } 
     - { path: /validateLogin, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    role_hierarchy: 
     ROLE_ADMIN:  ROLE_USER 

check_page से बाहर रखा गया है:

मैं एक security.yml विन्यास फाइल जो इस तरह दिखता है devcomments पर समान धागे पढ़ने के बाद "सुरक्षित" क्षेत्र।

मेरी रूटिंग कॉन्फ़िगरेशन में मैं प्रमाणीकरण के लिए दो नियमों में शामिल हैं:

_security_login: 
    pattern:      /login 
    defaults:  
     _controller:    PublicBundle:Auth:index 

_security_check: 
    pattern:      /validateLogin 

इकाई वर्ग मैं एक उपयोगकर्ता का प्रतिनिधित्व करने का उपयोग कर रहा एक Doctrine2 इकाई है और AccountInterface लागू करता है:

<?php 

namespace Application\AdminBundle\Entity; 

use Symfony\Component\Security\User\AccountInterface; 

/** 
* @orm:Entity 
*/ 
class User implements AccountInterface 
{ 
/** 
* @orm:Id 
* @orm:Column(type="integer") 
* @orm:GeneratedValue(strategy="IDENTITY") 
*/ 
protected $id; 
/** 
* @orm:Column(type="string", length="255") 
*/ 
protected $username; 
/** 
* @orm:Column(type="string", length="40") 
*/ 
protected $password; 

public function getId() 
{ 
    return $this->id; 
} 

public function setId($id) 
{ 
    $this->id = $id; 
} 

public function getUsername() 
{ 
    return $this->username; 
} 

public function setUsername($username) 
{ 
    $this->username = $username; 
} 

public function getPassword() 
{ 
    return $this->password; 
} 

public function setPassword($password) 
{ 
    $this->password = $password; 
} 

/** 
* Implementing the AccountInterface interface 
*/ 
public function __toString() 
{ 
    return $this->getUsername(); 
} 

public function getRoles() 
{ 
    return array('ROLE_ADMIN'); 
} 

public function eraseCredentials() 
{ 

} 

public function getSalt() 
{ 
    return $this->getId(); 
} 
} 

में क्लास ऑथकंट्रोलर मैं symfony2 दस्तावेज़ों से उदाहरण कोड का उपयोग कर रहा हूं:

public function indexAction() 
{ 
    if ($this->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { 
     $error = $this->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR); 
    } else { 
     $error = $this->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR); 
    } 

    return 
     $this->render(
      'PublicBundle:Auth:index.twig', 
      array(
       'last_username' => $this->get('request')->getSession()->get(SecurityContext::LAST_USERNAME), 
       'error' => $error)); 
} 

अब समस्या आता है: http://symfony2.localhost/app_dev.php/admin/testhttp://symfony2.localhost/app_dev.php/login के कार्यों से पुनर्निर्देशन नियम लेकिन उपयोगकर्ता नाम/पासवर्ड में प्रवेश करने और प्रवेश फार्म जमा करने के बाद, मैंने एक त्रुटि संदेश के बिना फिर से प्रवेश URL पर रीडायरेक्ट किया जा रहा हूँ।

मुझे पता है कि यह शायद एक बहुत बुनियादी मुद्दा है लेकिन बाद से वहाँ अभी तक symfony2 पर ज्यादा प्रलेखन नहीं है, मुझे लगता है कि यह इस तरह सवाल पूछने के लिए एक अच्छी जगह है। सामान्य रूप से एक सिम्फनी 2 प्रोजेक्ट के अंदर कुछ बिंदु हैं जो जादुई रूप से काम कर रहे हैं (निश्चित रूप से डी-बैकड) जो सीखने की प्रक्रिया को थोड़ा कठिन बनाते हैं। कैसे काम करता है प्रमाणीकरण पर मेरे विचार, कुछ जादुई नियंत्रक जो validateLogin कार्रवाई फैल जाती है कि वहाँ है मेरी उपयोगकर्ता इकाई के लिए एक इकाई के भंडार के लिए लग रहा है, findOneBy ('उपयोगकर्ता नाम' => $ उपयोगकर्ता नाम) कॉल और पासवर्ड तुलना ... यह है सही?

किसी भी संकेत के लिए अग्रिम धन्यवाद, अब मैं अधिक कुछ घंटों के लिए इस मुद्दे को googling किया गया है ... :)

पॉल

उत्तर

20

कैसे प्रमाणीकरण काम करता है पर मेरे विचार, कुछ जादुई नियंत्रक जो validateLogin कार्रवाई फैल जाती है कि वहाँ है मेरी उपयोगकर्ता इकाई के लिए एक इकाई के भंडार के लिए लग रहा है, कहता है findOneBy ('उपयोगकर्ता नाम' => $ उपयोगकर्ता नाम) और तुलना पासवर्ड ... क्या यह सही है?

आप गलत हैं। प्रमाणीकरण में कोई नियंत्रक शामिल नहीं होता है, यही कारण है कि आप _security_check मार्ग में कोई भी निर्दिष्ट नहीं करते हैं। एथ EventDispatcher पर आधारित है। जब भी आप अपने फ़ायरवॉल में कुछ श्रोता निर्दिष्ट (जैसे। form_login, anonymous, logout आदि) आप वास्तव में एक नया श्रोता core.security घटना के लिए रजिस्टर। Symfony\Component\HttpKernel\Security\Firewall::handle() एक ऐसा स्थान है जहां ये श्रोताओं वास्तव में पंजीकृत हैं।

सामान्य, सरल बनाया प्रवाह:

  1. उपयोगकर्ता लॉगिन प्रपत्र (_username और _password क्षेत्रों) भरता है।
  2. अनुरोध Symfony2 द्वारा संभाला जाता है।
  3. core.security ईवेंट निकाल दिया गया है।
  4. EventDispatcher सभी श्रोताओं को सूचित करता है।
  5. UsernamePasswordFormAuthenticationListener (handle() विधि) निकाल दिया जाता है और जाँच करता है कि:
    1. यूआरएल check_path विकल्प मेल खाता है।
    2. अनुरोध में _username और _password पैरामीटर दोनों हैं।
  6. श्रोता उपयोगकर्ता (attemptAuthentication() विधि) प्रमाणीकृत करने का प्रयास करता है।
  7. प्रमाणीकरण प्रबंधक सभी पंजीकृत प्रदाताओं को आग लगा देता है।
  8. अंत में, DaoAuthenticationProvider निकाल दिया गया है और यह डॉक्टर के उपयोगकर्ता भंडार वर्ग का उपयोग कर उपयोगकर्ता को पुनर्प्राप्त करने का प्रयास करता है।
  9. यदि सबकुछ ठीक है UsernamePasswordToken (जिसमें ऑब्जेक्ट loadUserByUsername() विधि द्वारा लौटाया गया है) वापस किया जा रहा है और उपयोगकर्ता को रीडायरेक्ट किया गया है।

वास्तव में सुरक्षा तंत्र काफी जटिल और समझने में मुश्किल है (दस्तावेज़ीकरण अभी भी समाप्त नहीं हुआ है)। लेकिन जब आप अंत में समझते हैं कि यह कैसे काम करता है तो आप देखेंगे कि यह कितना शक्तिशाली तंत्र है।


मैंने अपना खुद का प्रमाणीकरण तंत्र लिखा और यह ठीक काम करता है।

  1. विन्यास:

    मैं कस्टम प्रदाता और एनकोडर उपयोग कर रहा हूँ।

    security.config: 
        providers: 
         main: 
          id:   project.user_repository # DI id. Doctrine's UserRepositry 
          check_path: /login-check 
        encoders: 
         main: 
          class: Project\SiteBundle\Entity\User 
          id: security.encoder.sha512  # DI id. Service %security.encoder.digest.class% (with "sha512" as first parameter) 
        firewalls: 
         restricted: 
          pattern: /panel/.* 
          form_login: 
           check_path: /login-check 
         public: 
          pattern: /.* 
          anonymous: true 
          form_login: 
           check_path: /login-check 
          logout:  true 
        access_control: 
         - { path: /panel/.*, role: ROLE_USER } 
         - { path: /.*, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    

    आप /panel/* देख सकते हैं सीमित है, जबकि /* सार्वजनिक है।

    <service id="security.encoder.sha512" class="%security.encoder.digest.class%"> 
        <argument>sha512</argument> 
    </service> 
    
  2. Project\SiteBundle\Entity\User:

    /** 
    * @orm:Entity(repositoryClass="Project\SiteBundle\Repository\UserRepository") 
    */ 
    class User implements AdvancedAccountInterface { 
        /** 
        * @orm:Id @orm:Column(type="integer") 
        * @orm:GeneratedValue(strategy="AUTO") 
        */ 
        protected $id; 
    
        /** 
        * @orm:Column(unique=true, nullable=true) 
        */ 
        protected $email; 
    
        /** 
        * @orm:Column(unique=true, nullable=true) 
        */ 
        protected $xmpp; 
    
        /** 
        * @orm:Column(length=128) 
        */ 
        protected $password; 
    
        /** 
        * @orm:Column(length=16) 
        */ 
        protected $salt; 
    
        // User can be logged in using email address or xmpp adress. 
    
        // Dozens of getters/setters here. 
    } 
    
  3. Project\SiteBundle\Repository\UserRepository

    class UserRepository extends EntityRepository implements UserProviderInterface { 
        public function loadUserByUsername($username) { 
         $dql = sprintf(' 
          SELECT u 
          FROM %s u 
          WHERE u.email = :id OR u.xmpp = :id 
         ', $this->_entityName); 
    
         $user = null; 
    
         try { 
          $user = $this->_em->createQuery($dql)->setParameter('id', $username)->getSingleResult(); 
         } catch (ORMException $e) { 
          throw new UsernameNotFoundException("User $username not found.", $e->getCode(), $e); 
         } 
    
         return $user; 
        } 
    
        public function loadUserByAccount(AccountInterface $user) { 
         return $this->loadUserByUsername($user->getUsername()); 
        } 
    } 
    
  4. सुरक्षा मार्गों और नियंत्रण

  5. सेवा security.encoder.sha512 निर्मित एक एनकोडर है लेयर आपके जैसा ही है।

+0

वाह, उत्तर के लिए धन्यवाद! मैं इसे बाद में सम्मान करने की कोशिश करूंगा! – Paul

4

आप https://github.com/FriendsOfSymfony/FOSUserBundle FOS UserBundle का उपयोग करना चाहिए, यह इस सब के साथ लागू करता है सिद्धांत 2 और इसमें कई विशेषताएं हैं।

+0

धन्यवाद, मैंने इसे कुछ समय पहले देखा है। फिर भी मुझे यह जानकर खुशी होगी कि वहां क्या हो रहा है ... ऐसा लगता है कि मुझे कुछ और सिम्फनी कोड पढ़ना है :) – Paul

+1

उपयोगकर्ताबंडल के लिए कुछ सेटअप कैसे करें [यहां] (https://github.com /FriendsOfSymfony/UserBundle/blob/master/Resources/doc/index.rst), लेकिन मुझे एक ट्यूटोरियल देखना अच्छा लगेगा जो बंडल को लॉग इन/साइनअप फॉर्म कैसे प्राप्त करें, इस बारे में बताता है। इस बीच, मैं पढ़ रहा हूं, चीजों को तोड़ रहा हूं, और कुछ और पढ़ रहा हूं। – Banjer

1

कारण, अनिवार्य रूप से, क्यों प्रवेश पृष्ठ लोड फिर से बिना कोई त्रुटि संदेश, क्योंकि विडंबना यह है कि, अपनी सुरक्षा सेटिंग प्रवेश पृष्ठ पर गुमनाम उपयोग की अनुमति के लिए सेट नहीं कर रहे हैं।