Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>My thoughts on how the authentication works is that there is some magical Controller which catches the validateLogin action, looks for an entity repository for my User entity, calls findOneBy('username' => $username) and compares the passwords... is this right?</p> </blockquote> <p>You're wrong. Authentication doesn't involve any controller, that's why you don't specify any in <code>_security_check</code> route. Auth is based on <a href="http://components.symfony-project.org/event-dispatcher/" rel="noreferrer"><code>EventDispatcher</code></a>. Whenever you specify some listener in your firewall (eg. <code>form_login</code>, <code>anonymous</code>, <code>logout</code> etc.) you actually register a new listener for <code>core.security</code> event. <code>Symfony\Component\HttpKernel\Security\Firewall::handle()</code> is a place where these listeners are actually registered.</p> <p>The general, simplified flow:</p> <ol> <li>User fills login form (<code>_username</code> and <code>_password</code> fields).</li> <li>Request is handled by Symfony2.</li> <li><code>core.security</code> event is fired.</li> <li>EventDispatcher notifies all listeners.</li> <li><code>UsernamePasswordFormAuthenticationListener</code> is fired (<code>handle()</code> method) and checks whether: <ol> <li>URL matches <code>check_path</code> option.</li> <li>Request has both <code>_username</code> and <code>_password</code> parameters.</li> </ol></li> <li>Listener tries to authenticate user (<code>attemptAuthentication()</code> method).</li> <li>Authentication manager fires all registered providers.</li> <li>Finally, <code>DaoAuthenticationProvider</code> is fired and it tries to retrieve user using Doctrine's user repository class.</li> <li>If everything is fine <code>UsernamePasswordToken</code> (which contain <code>$user</code> object returned by <code>loadUserByUsername()</code> method) is being returned and user is redirected.</li> </ol> <p>Indeed security mechanism is quite complex and hard to understand (documentation isn't still finished). But when you finally understand how it works then you'll see how powerful mechanism it is.</p> <hr> <p>I wrote my own authentication mechanism and it works fine. </p> <ol> <li><p>Configuration:</p> <p>I'm using custom provider and encoder.</p> <pre><code>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 } </code></pre> <p>As you can see <code>/panel/*</code> is restricted, while <code>/*</code> is public.</p></li> <li><p>Service <code>security.encoder.sha512</code> is a built-in encoder:</p> <pre><code>&lt;service id="security.encoder.sha512" class="%security.encoder.digest.class%"&gt; &lt;argument&gt;sha512&lt;/argument&gt; &lt;/service&gt; </code></pre></li> <li><p><code>Project\SiteBundle\Entity\User</code>:</p> <pre><code>/** * @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. } </code></pre></li> <li><p><code>Project\SiteBundle\Repository\UserRepository</code></p> <pre><code>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-&gt;_entityName); $user = null; try { $user = $this-&gt;_em-&gt;createQuery($dql)-&gt;setParameter('id', $username)-&gt;getSingleResult(); } catch (ORMException $e) { throw new UsernameNotFoundException("User $username not found.", $e-&gt;getCode(), $e); } return $user; } public function loadUserByAccount(AccountInterface $user) { return $this-&gt;loadUserByUsername($user-&gt;getUsername()); } } </code></pre></li> <li><p>Security routes and controller is same as yours.</p></li> </ol>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload