2013-05-10 81 views
2

我在使用Silex和安全服务时遇到了一些小问题。成功登录后Silex不直接登录

当用户输入他的数据(正确)到我的登录表单中时,它不会被重定向到应用程序url。他仍然在同一页面中,并且在登录表单页面中进行调试时没有任何安全提供程序表明他已通过身份验证。但是,在“成功登录”之后,如果我直接在浏览器中输入网址,则可以访问,因为我已通过身份验证。事情是这样的过程:

首页 - >登录检查(登录OK) - >主页(未经认证) - > /应用程序(认证)

我想它直接重定向到如果/应用登录工作正常,并理解为什么在我的主页上,即使成功登录后,安全提供程序仍然说我没有通过身份验证。

我写的跟随着代码:

的index.php

<?php 

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\Validator\Constraints as Assert; 

require_once __DIR__.'/../vendor/autoload.php'; 

$app = new Silex\Application(); 

/** 
* App Registrations & Debug Setting 
*/ 

$app 
    ->register(new Silex\Provider\TwigServiceProvider(), array('twig.path' => __DIR__.'/../views')) 
    ->register(new Silex\Provider\UrlGeneratorServiceProvider()) 
    ->register(new Silex\Provider\SessionServiceProvider()) 
    ->register(new Silex\Provider\FormServiceProvider()) 
    ->register(new Silex\Provider\ValidatorServiceProvider()) 
    ->register(new Silex\Provider\TranslationServiceProvider(), array(
     'translator.messages' => array(), 
    )) 
    ->register(new Silex\Provider\DoctrineServiceProvider(), array(
     'db.options' => array(
      'driver' => 'pdo_mysql', 
      'dbname' => 'pomodesk', 
      'host'  => 'localhost', 
      'user'  => 'root', 
      'password' => 'root' 
     ) 
    )) 
    ->register(new Silex\Provider\SecurityServiceProvider(), array(
     'security.firewalls' => array(
      'app' => array(
       'pattern' => '^/app', 
       'http' => true, 
       'form' => array('login_path' => '/', 'check_path' => '/app/login_check'), 
       'logout' => array('logout_path' => '/app/logout'), 
       'anonymous' => false, 
       'users' => $app->share(function() use ($app) { 
        return new Pomodesk\Provider\UserProvider($app['db']); 
       }) 
      ), 
     ), 
     'security.access_rules' => array(
      array('^/app', 'ROLE_USER') 
     ) 
    )); 

$app['debug'] = true; 

/** 
* App Routes 
*/ 

$app->get('/', function(Request $request) use ($app) { 

    $form = $app['form.factory'] 
     ->createBuilder('form') 
     ->add('name', 'text') 
     ->add('email', 'text') 
     ->add('password', 'password') 
     ->getForm(); 

    if ('POST' == $request->getMethod()) { 
     $form->bind($request); 

     $data = $form->getData(); 

     $constraint = new Assert\Collection(array(
      'name'  => array(new Assert\Length(array('min' => 5)), new Assert\NotBlank()), 
      'email' => new Assert\Email(), 
      'password' => array(new Assert\Length(array('min' => 6)), new Assert\NotBlank()) 
     )); 

     $errors = $app['validator']->validateValue($data, $constraint); 

     $userProvider = new Pomodesk\Provider\UserProvider($app['db']); 

     try { 
      $duplicated = $userProvider->loadUserByUsername($data['email']); 
     } catch (Exception $e) { 
      $duplicated = false; 
     } 

     if ($form->isValid() && count($errors) < 1 && !$duplicated) { 
      $user = new \Symfony\Component\Security\Core\User\User($data['email'], '', array('ROLE_USER')); 

      $encoder = $app['security.encoder_factory']->getEncoder($user); 

      $insertion = $app['db']->insert(
       'user', 
       array(
        'email' => $data['email'], 
        'name'  => $data['name'], 
        'password' => $encoder->encodePassword($data['password'], $user->getSalt()), 
        'roles' => 'ROLE_USER' 
       ) 
      ); 

      return $app['twig']->render('home.html.twig', array(
       'username' => $data['email'], 
       'signup' => true 
      )); 
     } 

     return $app['twig']->render('home.html.twig', array(
      'username' => $data['email'], 
      'signup' => true 
     )); 
    } 

    return $app['twig']->render('home.html.twig', array(
     'error'   => $app['security.last_error']($request), 
     'last_username' => $app['session']->get('_security.last_username'), 
     'form'   => $form->createView() 
    )); 
}) 
->method('GET|POST') 
->bind('home'); 

$app->get('/app', function() use ($app) { 

    $app['app_js'] = $app['twig']->render('script.js.twig'); 
    $data = array(); 

    return $app['twig']->render('app.html.twig', $data); 
}) 
->bind('app_home'); 

$app->run(); 

UserProvider.php

<?php 

namespace Pomodesk\Provider; 

use Symfony\Component\Security\Core\User\UserProviderInterface; 
use Symfony\Component\Security\Core\User\UserInterface; 
use Symfony\Component\Security\Core\User\User; 
use Symfony\Component\Security\Core\Exception\UnsupportedUserException; 
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; 
use Doctrine\DBAL\Connection; 

class UserProvider implements UserProviderInterface 
{ 
    private $conn; 

    public function __construct(Connection $conn) 
    { 
     $this->conn = $conn; 
    } 

    public function loadUserByUsername($username) 
    { 
     $stmt = $this->conn->executeQuery('SELECT * FROM user WHERE email = ?', array(strtolower($username))); 

     if (!$user = $stmt->fetch()) { 
      throw new UsernameNotFoundException(sprintf('Email "%s" does not exist.', $username)); 
     } 

     return new User($user['email'], $user['password'], explode(',', $user['roles']), true, true, true, true); 
    } 

    public function refreshUser(UserInterface $user) 
    { 
     if (!$user instanceof User) { 
      throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); 
     } 

     return $this->loadUserByUsername($user->getUsername()); 
    } 

    public function supportsClass($class) 
    { 
     return $class === 'Symfony\Component\Security\Core\User\User'; 
    } 
} 

非常感谢!

回答

5

更改您的代码如下所示:

->register(new Silex\Provider\SecurityServiceProvider(), array(
      'security.firewalls' => array(
       'app' => array(
        'pattern' => '^/', 
        'http' => true, 
        'form' => array('login_path' => '/', 'check_path' => '/app/login_check'), 
        'logout' => array('logout_path' => '/app/logout'), 
        'anonymous' => true, 
        'users' => $app->share(function() use ($app) { 
         return new Pomodesk\Provider\UserProvider($app['db']); 
        }) 
       ), 
      ), 
      'security.access_rules' => array(
       array('^/app', 'ROLE_USER') 
      ) 
     )); 

允许匿名用户在防火墙,只是保护与访问规则/应用程序路径。如果你不这样做,你会遇到问题的上下文,假设你想要一个自定义菜单,如果用户在你的应用程序的所有页面上登录,即使那些没有安全的,你将无法做到这一点,如果你不会在所有网站上分享安全上下文。

这些都是一些可以在形式阵列中使用的选项,根据symfony的DOC:

  # login success redirecting options (read further below) 
      always_use_default_target_path: false 
      default_target_path:   /
      target_path_parameter:   _target_path 
      use_referer:     false 

​​

所以重定向可以通过一个隐藏的输入登录表单,或设置来处理default_target_path

'form' => array(
    'login_path' =>      '/', 
    'check_path' =>      '/app/login_check', 
    'default_target_path' =>   '/app', 
    'always_use_default_target_path' => true 
), 
+0

非常感谢! – joaobarbosa 2013-05-13 12:37:46

+0

嗨你有一个GitHub的登录?我还需要一个登录过程,我可以有你的工作副本,所以我可以尝试在我的本地? – knives22 2015-12-22 01:46:03