<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SecurityBundle | Nerdpress.org</title>
	<atom:link href="https://nerdpress.org/tag/securitybundle/feed/" rel="self" type="application/rss+xml" />
	<link>https://nerdpress.org</link>
	<description>...dev, tech problems and solutions.</description>
	<lastBuildDate>Fri, 14 Oct 2011 09:20:43 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>[Symfony 2] Security Bundle: Set User Locale on Form Login</title>
		<link>https://nerdpress.org/2011/08/14/symfony-2-security-bundle-set-user-locale-on-form-login/</link>
					<comments>https://nerdpress.org/2011/08/14/symfony-2-security-bundle-set-user-locale-on-form-login/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Sun, 14 Aug 2011 10:15:30 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Project Setup]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[DIC]]></category>
		<category><![CDATA[EventListener]]></category>
		<category><![CDATA[SecurityBundle]]></category>
		<category><![CDATA[Services]]></category>
		<category><![CDATA[symfony 2]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1574</guid>

					<description><![CDATA[<p>Anleitung, wie die User-Locale on Login unter anderem über den Symfony Event-Dispatcher zu setzen ist.</p>
The post <a href="https://nerdpress.org/2011/08/14/symfony-2-security-bundle-set-user-locale-on-form-login/">[Symfony 2] Security Bundle: Set User Locale on Form Login</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p><strong>[UPDATE]</strong><br />
A recent update to this article may be found here: <a href="https://nerdpress.org/2011/10/13/symfony-2-set-default-locale-on-form-login-2/">https://nerdpress.org/symfony-2-set-default-locale-on-form-login-2/</a></p>
<p>Das Security Bundle ist ein wenig magisch. Da muss man eine HTML-Form definieren, der Rest wird irgendwie konfiguriert (Namen der Post-Parameter wie &#8220;_username&#8221;, &#8220;_password&#8221; etc., den Redirect zum Referrer, Remember-Me Funktion und so weiter, das alles wird von der Firewall intern geregelt. Man muss nur eine Login-Route definieren, einen Stub-Controller + Action-Callable (der aber nie ausgeführt wird, weil die Firefall sich davorhängt), fertig.</p>
<p>Das ist angenehm einfach, solange man keine Fragen stellt. Aber wie führe ich zusätzliche Aktionen direkt nach erfolgtem Login aus, ohne Einfuss auf den Code des Security Bundles zu haben?</p>
<p><span id="more-1574"></span></p>
<p>Meist sucht man dazu einen Hook, Einstiegspunkt oder eine Konfigurationsvariable. In Symfony 2 sucht man natürlich Events, doch die Doku schweigt sich hierzu noch ein wenig aus, also wieder &#8216;rein in den Sourcecode. Irgendwo muss doch eine Möglichkeit zu finden sein, und tatsächlich, im AbstractAuthentificationListener werden wir fündig:</p>
<p>vendorsymfonysrcSymfonyComponentSecurityHttpFirewallAbstractAuthentificationListener.php</p>
<pre class="brush: php; title: ; notranslate">

namespace SymfonyComponentSecurityHttpFirewall;

//...

abstract class AbstractAuthenticationListener implements ListenerInterface
{
    // ...
    private function onSuccess(GetResponseEvent $event, Request $request, TokenInterface $token)
    {
        if (null !== $this-&gt;logger) {
            $this-&gt;logger-&gt;info(sprintf('User &quot;%s&quot; has been authenticated successfully', $token-&gt;getUsername()));
        }

        $this-&gt;securityContext-&gt;setToken($token);

        $session = $request-&gt;getSession();
        $session-&gt;remove(SecurityContextInterface::AUTHENTICATION_ERROR);
        $session-&gt;remove(SecurityContextInterface::LAST_USERNAME);

        if (null !== $this-&gt;dispatcher) {
            $loginEvent = new InteractiveLoginEvent($request, $token);
            $this-&gt;dispatcher-&gt;dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
        }

        if (null !== $this-&gt;successHandler) {
            $response = $this-&gt;successHandler-&gt;onAuthenticationSuccess($request, $token);
        } else {
            $response = $this-&gt;httpUtils-&gt;createRedirectResponse($request, $this-&gt;determineTargetUrl($request));
        }

        if (null !== $this-&gt;rememberMeServices) {
            $this-&gt;rememberMeServices-&gt;loginSuccess($request, $response, $token);
        }

        return $response;
    }
</pre>
<p>Die Klasse ist nur auszugsweise abgedruckt. Interessant sind die Zeilen 233 &amp; 238 im Original-Sourcecode.</p>
<p>Zeile 233 ff. benachrichtigt alle Eventlistener, die auf SecurityEvents::INTERACTIVE_LOGIN hören, wenn ein Event-Dispatcher vorhanden ist (im Falle der Symfony Standard Distribution kann man das voraussetzen).</p>
<p>Zeile 238 ist eine Sonderlocke, sozusagen ein &#8220;Security-Bundle-eigenes&#8221; Event. Man hat die Möglichkeit, in der jeweiligen Firewall-Einstellung für den Form-Login in der security.yml mit success_handler einen eigenen DIC-Service anzugeben, der SymfonyComponentSecurityHttpAuthenticationAuthenticationSuccessHandlerInterface implementiert.</p>
<p>Das sieht dann in etwa so aus:</p>
<pre class="brush: python; title: ; notranslate">
      secured_area:
            pattern:    ^/demo/secured/
            form_login:
                check_path: /demo/secured/login_check
                login_path: /demo/secured/login
                success_handler: dvlp_core.login_success_handler
</pre>
<p>Die Implementierung der Callback-Methode onAuthenticationSuccess(Request $request, TokenInterface $token) des Interfaces ist aber nicht ganz trivial, da als Rückgabewert eben eine Instanz von SymfonyComponentHttpFoundationResponse erwartet wird, die man dann selbsttätig konfigurieren muss (inkl. Rücksprung-Adresse, Referer-Logik und Auswertung der Benutzerkonfiguration). Daher lassen wir das erstmal sein und nutzen den Event-Dispatcher, um uns in den Login hineinzukrallen. Dazu definieren wir einen neuen Service in einem unserer Bundles und taggen ihn als Eventlistener:</p>
<p>Resourcesconfigservices.xml:</p>
<pre class="brush: xml; title: ; notranslate">
    &lt;parameters&gt;
        &lt;parameter key=&quot;dvlp_core.event_listener.class&quot;&gt;DvlpCoreBundleEventListener&lt;/parameter&gt;
    &lt;/parameters&gt;
    &lt;service id=&quot;dvlp_core.event_listener&quot; class=&quot;%dvlp_core.event_listener.class%&quot;&gt;
        &lt;tag name=&quot;kernel.event_listener&quot; event=&quot;security.interactive_login&quot; method=&quot;onSecurityInteractiveLogin&quot; /&gt;
    &lt;/service&gt;
</pre>
<p>Dann implementieren wir den Listener. Dieser Listener soll die Session-Locale &#8220;on login&#8221; auf die Lokalisierungs-Einstellung des aktuellen (Datenbank-)-Users setzen.</p>
<p>DvlpCoreBundleEventListener.php:</p>
<pre class="brush: php; title: ; notranslate">
class EventListener
{
    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
    {
        $token = $event-&gt;getAuthenticationToken();
        $session = $event-&gt;getRequest()-&gt;getSession();
        $session-&gt;setLocale($token-&gt;getUser()-&gt;getLocale());
    }
}
</pre>
<p>Das war´s auch schon. Events to the Rescue. Leider scheinen diese wirklich noch nicht allzu ausführlich dokumentiert zu sein, ich wäre froh, wenn mir jemand das Gegenteil aufzeigen kann!</p>
<p>Viel Spaß beim Ausprobieren.</p>The post <a href="https://nerdpress.org/2011/08/14/symfony-2-security-bundle-set-user-locale-on-form-login/">[Symfony 2] Security Bundle: Set User Locale on Form Login</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2011/08/14/symfony-2-security-bundle-set-user-locale-on-form-login/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>[Symfony 2] Security Bundle &#8211; Benutzer mit username oder email anmelden.</title>
		<link>https://nerdpress.org/2011/08/12/symfony-2-security-bundle-benutzer-mit-username-oder-email-anmelden/</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 12 Aug 2011 13:04:36 +0000</pubDate>
				<category><![CDATA[DB]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Project Setup]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Doctrine 2]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SecurityBundle]]></category>
		<category><![CDATA[symfony 2]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1566</guid>

					<description><![CDATA[<p>Augenscheinlich unterstützt das Security-Modul in der Standard-Konfiguration nur die Authentifizierung via Benutzername und Password. Wie man sich mit einem Benutzernamen ODER der E-Mail-Adresse und einem Passwort authentifiziert, ist ein wenig versteckt. Das ist die Anleitung, wie es funktioniert.</p>
The post <a href="https://nerdpress.org/2011/08/12/symfony-2-security-bundle-benutzer-mit-username-oder-email-anmelden/">[Symfony 2] Security Bundle – Benutzer mit username oder email anmelden.</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Augenscheinlich unterstützt das Security-Module nur die Authentifizierung via Benutzername und Password. Wie man sich mit einem Benutzernamen ODER der E-Mail-Adresse und einem Password authentifiziert, ist ein wenig versteckt. So gehts:</p>
<p><span id="more-1566"></span></p>
<p>Schaut man sich den generischen EntityUserProvider an, so sieht man ab Zeile 46 sowas wie</p>
<pre class="brush: php; title: ; notranslate">
    /**
     * {@inheritdoc}
     */
    public function loadUserByUsername($username)
    {
        if (null !== $this-&gt;property) {
            $user = $this-&gt;repository-&gt;findOneBy(array($this-&gt;property =&gt; $username));
        } else {
            if (!$this-&gt;repository instanceof UserProviderInterface) {
                throw new InvalidArgumentException(sprintf('The Doctrine repository &quot;%s&quot; must implement UserProviderInterface.', get_class($this-&gt;repository)));
            }

            $user = $this-&gt;repository-&gt;loadUserByUsername($username);
        }

        if (null === $user) {
            throw new UsernameNotFoundException(sprintf('User &quot;%s&quot; not found.', $username));
        }

        return $user;
    }
</pre>
<p>Dieser Code besagt, dass nur dann, wenn die Konfigurationeinstellung &#8220;property&#8221; aus der security.yml entfernt wird (steht üblicherweise auf &#8220;username&#8221; und gibt das Datenbankattribut an, das eben den Benutzernamen hält), das entsprechende Doctrine-Entity &#8220;User&#8221; auch eine Repository-Class hat und diese darüber hinaus UserProviderInterface implementiert, man seine eigene loadUserByUsername()-Methode implementieren kann, die dann von der Firewall zur Identifizierung des Benutzer beim Login herangezogen wird (dieser Vorgang ist komplett intransparent, Symfony Magic).</p>
<p>Also aus seiner &#8220;alten&#8221; security.yml</p>
<pre class="brush: python; title: ; notranslate">
    providers:
        default:
            users:
                user:  { password: userpass, roles: &#x5B; 'ROLE_USER' ] }
                admin: { password: adminpass, roles: &#x5B; 'ROLE_ADMIN' ] }
            entity: { class: DvlpCoreBundleEntityUser, property: username }
</pre>
<p>sowas machen:</p>
<pre class="brush: python; title: ; notranslate">
     ...
            entity: { class: DvlpCoreBundleEntityUser }
</pre>
<p>Dann muss das zu User gehörtige UserRepository nur noch UserProviderInterface implementieren, bspw. so:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

namespace DvlpCoreBundleEntity;

use DoctrineORMEntityRepository;
use SymfonyComponentSecurityCoreUserUserProviderInterface;
use SymfonyComponentSecurityCoreUserUserInterface;

/**
 * UserRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class UserRepository extends EntityRepository implements UserProviderInterface
{
    /**
     * {@inheritdoc}
     */
    public function loadUserByUsername($username)
    {
        return $this-&gt;getEntityManager()
            -&gt;createQuery('SELECT u FROM DvlpCoreBundle:User u JOIN u.Profile p WHERE u.username = :username OR p.email = :username')
            -&gt;setParameters(array(
                'username' =&gt; $username
            ))
            -&gt;getOneOrNullResult();
    }

    /**
     * {@inheritDoc}
     */
    public function refreshUser(UserInterface $user)
    {
        return $this-&gt;loadUserByUsername($user-&gt;getUsername());
    }

    /**
     * {@inheritDoc}
     */
    public function supportsClass($class)
    {
        // NEVER CALLED ...
        return $class === 'DvlpCoreBundleEntityUser';
    }
}
}
</pre>
<p>Schon kann man als Benutzernamen entweder den Username oder die E-Mail-Adresse des Users angeben.</p>The post <a href="https://nerdpress.org/2011/08/12/symfony-2-security-bundle-benutzer-mit-username-oder-email-anmelden/">[Symfony 2] Security Bundle – Benutzer mit username oder email anmelden.</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
