2012-08-14 335 views
1

我的項目中有以下代碼文件,這些文件完全與自定義身份驗證提供程序相關,並且我可以在身份驗證(TokenInterface $ token)中攔截請求,我已將回顯「 「;出口;在屏幕上打印消息讓我知道它在文件AuthProvider.php中輸入了authenticate()。symfony2 login_check和自定義身份驗證提供程序

但是,當我試圖改變login_path問題上升:/登錄login_path:/用戶/註冊check_path:/ login_checkcheck_path:/用戶/ login_check並修改路由.yml讓UserBundle有前綴/用戶,然後代碼將工作,但它不會進入身份驗證(),但它會打印「所提出的密碼無效」的代替「壞憑據」 ,我如何將login_check & check_path更改爲其他值分別登錄& login_check和讓我的自定義身份驗證提供程序使用新的設置?

//應用/配置/ security.yml

security: 
    factories: 
     - "%kernel.root_dir%/../src/FD/UserBundle/Resources/config/security_factories.yml" 

    firewalls: 
     checkpoint: 
      pattern: ^/ 
      user: true 
      form_login: 
       login_path: /login 
       check_path: /login_check 
      logout: 
       path: /logout 
       target:/
      anonymous: ~ 

    encoders: 
     FD\UserBundle\Entity\User: sha512 

    role_hierarchy: 
     ROLE_ADMIN:  ROLE_USER 
     ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] 

    providers: 
     user_provider: 
      id: user_provider_service 

    access_control: 
     - { path: ^/_internal, role: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } 
     - { path: ^/user/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } 
     - { path: ^/event/new, roles: ROLE_ADMIN } 
     - { path: ^/hello, roles: ROLE_USER } 

//應用/配置/ config.yml

imports: 
    - { resource: parameters.ini } 
    - { resource: security.yml } 
    - { resource: @UserBundle/Resources/config/services.yml } 

framework: 
    #esi:    ~ 
    translator:  { fallback: %locale% } 
    secret:   %secret% 
    charset:   UTF-8 
    router:   { resource: "%kernel.root_dir%/config/routing.yml" } 
    form:   true 
    csrf_protection: false 
    validation: { enabled: true } 
    #validation:  { enable_annotations: true } 
    templating:  { engines: ['twig'] } #assets_version: SomeVersionScheme 
    session: 
     default_locale: %locale% 
     auto_start:  true 

# Twig Configuration 
twig: 
    debug:   %kernel.debug% 
    strict_variables: %kernel.debug% 

# Assetic Configuration 
assetic: 
    debug:   %kernel.debug% 
    use_controller: false 
    # java: /usr/bin/java 
    filters: 
     cssrewrite: ~ 
     # closure: 
     #  jar: %kernel.root_dir%/java/compiler.jar 
     # yui_css: 
     #  jar: %kernel.root_dir%/java/yuicompressor-2.4.2.jar 

# Doctrine Configuration 
doctrine: 
    dbal: 
     default_connection: default 
     connections: 
      default:  
       driver: %database_driver% 
       host:  %database_host% 
       port:  %database_port% 
       dbname: %database_name% 
       user:  %database_user% 
       password: %database_password% 
       charset: UTF8 
       mapping_types: 
        enum: string 
        set: string 
        blob: object 
    orm: 
     auto_generate_proxy_classes: %kernel.debug%  
     default_entity_manager:   default # The first defined is used if not set 
     entity_managers: 
      default:  
       # The name of a DBAL connection (the one marked as default is used if not set) 
       connection: ~ 
       mappings: # Required 
        FDHelloBundle: ~ 
        UserBundle: { type: annotation } 

     # mappings: 
     # FDHelloBundle: { type: yml, dir: Resources/config/doctrine/metadata/orm }   

# Swiftmailer Configuration 
swiftmailer: 
    transport: %mailer_transport% 
    host:  %mailer_host% 
    username: %mailer_user% 
    password: %mailer_password% 

jms_security_extra: 
    secure_controllers: true 
    secure_all_services: false 

services: 
    fd_hello.twig.extension.debug: 
     class:  Twig_Extension_Debug 
     tags: 
      - { name: 'twig.extension' } 

    user_provider_service: 
     class: FD\UserBundle\Security\User\UserProvider 

//應用/配置/ routing.yml中

FDHelloBundle: 
    resource: "@FDHelloBundle/Resources/config/routing.yml" 
    prefix: /

FDUserBundle: 
    resource: "@UserBundle/Controller" 
    prefix: /user 
    type: annotation 

// SRC/FD/UserBundle /控制器/ LoginController.php

namespace FD\UserBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Component\Security\Core\SecurityContext; 

class LoginController extends Controller 
{ 
    /** 
    * @Route("login", name="login") 
    */ 
    public function loginAction() 
    { 
     $request = $this->getRequest(); 
     $session = $request->getSession(); 

     // get the login error if there is one 
     $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); 
     $session->remove(SecurityContext::AUTHENTICATION_ERROR); 

     return $this->render('UserBundle:Login:login.html.twig', array(
      // last username entered by the user 
      'last_username' => $session->get(SecurityContext::LAST_USERNAME), 
      'error'   => $error, 
     )); 
    } 

    /** 
    * @Route("login_check", name="login_check") 
    */ 
    public function loginCheckAction() 
    { 

    } 

    /** 
    * @Route("logout", name="logout") 
    */ 
    public function logoutAction() 
    { 

    } 
} 

// SRC/FD/UserBundle/DependencyInjection /安全/工廠/ UserFactory.php

namespace FD\UserBundle\DependencyInjection\Security\Factory; 

use Symfony\Component\DependencyInjection\ContainerBuilder; 
use Symfony\Component\DependencyInjection\Reference; 
use Symfony\Component\DependencyInjection\DefinitionDecorator; 
use Symfony\Component\Config\Definition\Builder\NodeDefinition; 
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface; 

class UserFactory implements SecurityFactoryInterface 
{ 
    public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) 
    { 
     $providerId = 'security.authentication.provider.user.'.$id; 
     $container 
      ->setDefinition($providerId, new DefinitionDecorator('user.security.authentication.provider')) 
      ->replaceArgument(0, new Reference($userProvider)) 
     ; 
     $listenerId = 'security.authentication.listener.user.'.$id; 
     $listener = $container->setDefinition($listenerId, new DefinitionDecorator('user.security.authentication.listener')); 

     return array($providerId, $listenerId, $defaultEntryPoint); 
    } 

    public function getPosition() 
    { 
     return 'pre_auth'; 
    } 

    public function getKey() 
    { 
     return 'user'; 
    } 

    public function addConfiguration(NodeDefinition $node) 
    {} 
} 

// FD/UserBundle/Resources/config/services.yml

services: 
    user.security.authentication.provider: 
     class: FD\UserBundle\Security\Authentication\Provider\AuthProvider 
     arguments: ['', %kernel.cache_dir%/security/nonces] 

    user.security.authentication.listener: 
     class: FD\UserBundle\Security\Firewall\AuthListener 

// FD/UserBundle /資源/配置/ security_factories.yml

services: 
    security.authentication.factory.user: 
     class: FD\UserBundle\DependencyInjection\Security\Factory\UserFactory 
     tags: 
      - { name: security.listener.factory } 

// FD/UserBundle /安全/認證/供應商/ AuthProvider.php

namespace FD\UserBundle\Security\Authentication\Provider; 

use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; 
use Symfony\Component\Security\Core\User\UserProviderInterface; 
use Symfony\Component\Security\Core\Exception\AuthenticationException; 
use Symfony\Component\Security\Core\Exception\NonceExpiredException; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 
use Symfony\Component\Security\Core\Exception\BadCredentialsException; 

use FD\UserBundle\Security\Authentication\Token\UserToken; 

class AuthProvider implements AuthenticationProviderInterface 
{ 
    private $userProvider; 
    private $cacheDir; 

    public function __construct(UserProviderInterface $userProvider, $cacheDir) 
    { 
     $this->userProvider = $userProvider; 
     $this->cacheDir  = $cacheDir; 
    } 

    public function authenticate(TokenInterface $token) 
    { 
//  $user = $this->userProvider->loadUserByUsername($token->getUsername()); 
//  $userToken = new UserToken(); 
//  $userToken->setUser($user); 
echo "it worked"; exit; 
     $newToken = new UserToken($token->getUser(), $token->getCredentials(), "user", array("ROLE_ADMIN")); 
     $username = $newToken->getUser(); 
     if (empty($username)) { 
      throw new BadCredentialsException('Bad credentials :)'); 
     } 
     return $newToken; 

//  if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) { 
//   $authenticatedToken = new UserToken($user->getRoles()); 
//   $authenticatedToken->setUser($user); 
// 
//   return $authenticatedToken; 
//  } 
    } 

    public function supports(TokenInterface $token) 
    { 
     return $token instanceof UserToken; 
    } 
} 

// FD/UserBundle/Security/Authenticaion/Token/UserToken.php

namespace FD\UserBundle\Security\Authentication\Token; 

use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; 

/** 
* UsernamePasswordToken implements a username and password token. 
* 
*/ 

class UserToken extends AbstractToken 
{ 
    private $credentials; 
    private $providerKey; 

    /** 
    * Constructor. 
    * 
    * @param string $user  The username (like a nickname, email address, etc.) 
    * @param string $credentials This usually is the password of the user 
    * @param string $providerKey The provider key 
    * @param array $roles  An array of roles 
    * 
    * @throws \InvalidArgumentException 
    */ 
    public function __construct($user, $credentials, $providerKey, array $roles = array()) 
    { 
     parent::__construct($roles); 

     if (empty($providerKey)) { 
      throw new \InvalidArgumentException('$providerKey must not be empty.'); 
     } 

     $this->setUser($user); 
     $this->credentials = $credentials; 
     $this->providerKey = $providerKey; 

     parent::setAuthenticated(count($roles) > 0); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function setAuthenticated($isAuthenticated) 
    { 
     if ($isAuthenticated) { 
      throw new \LogicException('Cannot set this token to trusted after instantiation.'); 
     } 

     parent::setAuthenticated(false); 
    } 

    public function getCredentials() 
    { 
     return $this->credentials; 
    } 

    public function getProviderKey() 
    { 
     return $this->providerKey; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function eraseCredentials() 
    { 
     parent::eraseCredentials(); 

     $this->credentials = null; 
    } 

    public function serialize() 
    { 
     return serialize(array($this->credentials, $this->providerKey, parent::serialize())); 
    } 

    public function unserialize($str) 
    { 
     list($this->credentials, $this->providerKey, $parentStr) = unserialize($str); 
     parent::unserialize($parentStr); 
    } 
} 

// FD/UserBundle/Security/Firewall/AuthListener。PHP

namespace FD\UserBundle\Security\Firewall; 

use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpKernel\Event\GetResponseEvent; 
use Symfony\Component\Security\Http\Firewall\ListenerInterface; 
use Symfony\Component\Security\Core\Exception\AuthenticationException; 
use Symfony\Component\Security\Core\SecurityContextInterface; 
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 
use Symfony\Component\Security\Http\Firewall\AbstractAuthenticationListener; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; 
use Symfony\Component\Security\Http\HttpUtils; 


use FD\UserBundle\Security\Authentication\Token\UserToken; 

class AuthListener extends AbstractAuthenticationListener 
{ 
    protected $securityContext; 
    protected $authenticationManager; 
    protected $httpUtils; 

    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, 
           SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $options = array()) 
    { 
     parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, "user", array_merge(array(
      'username_parameter' => '_username', 
      'password_parameter' => '_password', 
      'intention' => 'authenticate', 
      'post_only' => true, 
     ), $options)); 
    } 

    /** 
    * Performs authentication. 
    * 
    * @param Request $request A Request instance 
    * 
    * @return TokenInterface The authenticated token, or null if full authentication is not possible 
    * 
    * @throws AuthenticationException if the authentication fails 
    */ 
    protected function attemptAuthentication(Request $request) 
    { 

     $username = trim($request->get($this->options['username_parameter'], null, true)); 
     $password = $request->get($this->options['password_parameter'], null, true); 

     //$request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username); 

     return $this->authenticationManager->authenticate(new UserToken($username, $password, $this->providerKey)); 

    } 

    public function getHttpUtils() 
    { 
     return $this->httpUtils; 
    } 

    public function setHttpUtils($httpUtils) 
    { 
     $this->httpUtils = $httpUtils; 
    } 
} 

// SRC/FD/UserBundle /安全/用戶/ UserProvider.php

namespace FD\UserBundle\Security\User; 

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

use FD\UserBundle\Entity\User; 

class UserProvider implements UserProviderInterface 
{ 
    public function loadUserByUsername($username) 
    { 
     // make a call to your webservice here 
     // $userData = ... 
     // pretend it returns an array on success, false if there is no user 
     $user = new User(); 
     $user->setUsername($username); 
     $user->setPassword("1234"); 
     $user->setRoles(array("ROLE_ADMIN")); 

     return $user; 

//  if ($userData) { 
//   // $password = '...'; 
//   // ... 
// 
//   return new WebserviceUser($username, $password, $salt, $roles) 
//  } else { 
//   throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); 
//  } 
    } 

    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 === 'FD\UserBundle\Entity\User'; 
    } 
} 

回答

1

好像你正在做的一切是正確的。

大概要導入錯誤的資源

FDUserBundle: 
    resource: "@UserBundle/Controller" 

它不應該是如下?

FDUserBundle: 
    resource: "@FDUserBundle/Controller" 
+0

嗨,「@UserBundle」是正確的而不是「@FDUserBundle」因爲我的包被定義爲:類UserBundle extneds捆綁{}中的src/FD/UserBundle – 2012-08-14 11:20:54

+0

我在應用改變check_path設置所作的測試/ config/security.yml,如果我使用check_path:/ login_check,那麼我發現我可以在** AuthProvider :: supports(TokenInterface $ token)**中接收到我的自定義** UserToken **,但是如果我更改**「check_path 「**到check_path:/ user/login_check,然後我收到一個** Symfony \ Component \ Security \ Core \ Authentication \ Token \ UsernamePasswordToken **類型的令牌,有人可以解釋爲什麼我在更改*時收到不同的令牌* *「check_path」**設置? – 2012-08-14 13:14:42

+0

可能是防火牆問題?嘗試爲/ user/login_check添加明確的驗證碼即可排除。 – Cerad 2012-08-14 15:57:00

相關問題