Lære baserte autentiseringsmekanisme i Symfony2 prosjekt

stemmer
14

Jeg jobber på en liten Doctrine2-støttet prosjekt med Symfony2 for første gang. Tiden jeg sliter med sikkerheten komponent av symfony2, for å være nøyaktig med autentiseringsmekanismen beskrevet i dokumentasjonen .

Jeg vil bruke et skjemabasert autentisering og gjorde alt fremgår av dokumenter:

Jeg har en security.yml konfigurasjonsfil som ser slik ut:

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

Den check_page er ekskludert fra secureless området etter å ha lest en tilsvarende gjenge på devcomments .

I min ruting konfigurasjonen inkluderer jeg to regler for godkjenning:

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

_security_check:
    pattern:                      /validateLogin

Foretaket klassen jeg bruker til å representere en bruker er en Doctrine2 enhet og implementerer 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();
}
}

I klassen AuthController jeg bruker eksempelet koden fra symfony2 dokumenter:

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));
}

Nå kommer problemet: The omdirigering regel fra http: //symfony2.localhost/app_dev.php/admin/test til http: //symfony2.localhost/app_dev.php/login gjerninger, men etter å ha tastet brukernavn / passord og sende innloggingsskjemaet , jeg blir omdirigert til innloggings url igjen uten en feilmelding.

Jeg vet at dette sannsynligvis er en veldig grunnleggende problemet, men siden er foreløpig ikke mye dokumentasjon på symfony2, tror jeg dette er et bra sted å stille spørsmål som dette. Generelt er det noen punkter inne i en symfony2 prosjekt som synes å bli arbeider magisk (selvfølgelig DI-støttet) som gjør læringsprosessen litt vanskelig. Mine tanker om hvordan autentisering fungerer er at det er noen magisk Controller som fanger validateLogin handling, ser for en enhet oppbevaringssted for min bruker enheten, kaller findOneBy ( 'brukernavn' => $ username) og sammenligner passord ... er dette Ikke sant?

Takk på forhånd for noen hint, jeg har vært googling dette nummeret for mer noen timer nå ... :)

Paul

Publisert på 16/01/2011 klokken 17:53
kilden bruker
På andre språk...                            


3 svar

stemmer
20

Mine tanker om hvordan autentisering fungerer er at det er noen magisk Controller som fanger validateLogin handling, ser for en enhet oppbevaringssted for min bruker enheten, kaller findOneBy ( 'brukernavn' => $ username) og sammenligner passord ... er dette Ikke sant?

Du tar feil. Autentisering innebærer ikke noen controller, det er derfor du ikke angir noen i _security_checkrute. Auth er basert på EventDispatcher. Når du angir noen lytteren i brannmuren (f.eks. form_login, anonymous, logoutEtc.) du faktisk registrere en ny lytte for core.securityhendelsen. Symfony\Component\HttpKernel\Security\Firewall::handle()er et sted hvor disse lytterne er faktisk registrert.

Den generelle, forenklet flyt:

  1. Bruker fyller login form ( _usernameog _passwordfelt).
  2. Request håndteres av Symfony2.
  3. core.security Arrangementet er avfyrt.
  4. EventDispatcher varsler alle lyttere.
  5. UsernamePasswordFormAuthenticationListenerer avfyrt ( handle()metode) og kontrollerer om:
    1. URL matcher check_pathalternativet.
    2. Request har både _usernameog _passwordparametere.
  6. Lytteren prøver å autentisere brukeren ( attemptAuthentication()metode).
  7. Authentication Manager branner alle registrerte leverandører.
  8. Endelig DaoAuthenticationProviderer avfyrt og den prøver å hente brukeren ved hjelp Lære bruker depot klasse.
  9. Hvis alt er i orden UsernamePasswordToken(som inneholder $usergjenstanden som returneres av loadUserByUsername()metode) blir returnert, og brukeren blir omdirigert.

Faktisk sikkerhetsmekanisme er ganske komplisert og vanskelig å forstå (dokumentasjon er ikke fortsatt ferdig). Men når du endelig forstår hvordan det fungerer så vil du se hvor kraftig mekanisme det er.


Jeg skrev min egen autentiseringsmekanisme og det fungerer fint.

  1. konfigurasjon:

    Jeg bruker tilpasset leverandøren og encoder.

    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 }
    

    Som du kan se /panel/*er begrenset, mens /*er offentlig.

  2. Tjenesten security.encoder.sha512er en innebygd encoder:

    <service id="security.encoder.sha512" class="%security.encoder.digest.class%">
        <argument>sha512</argument>
    </service>
    
  3. 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.
    }
    
  4. 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());
        }
    }
    
  5. Sikkerhet ruter og kontrolleren er samme som din.

Svarte 23/01/2011 kl. 12:42
kilden bruker

stemmer
4

Du bør bruke https://github.com/FriendsOfSymfony/FOSUserBundle FOS UserBundle, det implementerer alt dette med Lære to og har tonnevis av funksjoner.

Svarte 19/01/2011 kl. 22:42
kilden bruker

stemmer
1

Grunnen, i hovedsak, hvorfor login siden lastes på nytt uten feilmelding er fordi, ironisk nok, er sikkerhetsinnstillingene ikke satt opp til å tillate anonym tilgang til påloggingssiden.

Svarte 30/01/2011 kl. 23:36
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more