2

我有一个通过 domain.com/index.html 提供的 AngularJS 前端。我的 API 调用都在 domain.com/api/* 的同一个域范围内。我想启用标准用户名/密码身份验证。但是,我需要 Silex 后端做的只是设置会话并在登录时返回 200 成功或 401 失败状态代码。我从 silex, symfony2 docs 中找到了一些代码,但就是不能完全正确。我基本上设置了我的自定义成功/失败自定义处理程序以返回代码并将它们应用于防火墙。我在防火墙/表单设置中的“check_path”似乎是唯一重要的真正和平。

这是大部分代码。希望它的格式足够好,可以为您提供帮助。谢谢!

应用程序.php

// Setup sessions
$app->register(new Silex\Provider\SessionServiceProvider());

// General Service Provder for Controllers
$app->register(new Silex\Provider\ServiceControllerServiceProvider());

$app['security.authentication.success_handler.auth'] = $app->share(function ($app) {
    return new ChrDb\Security\AuthSuccessHandler();
});

$app['security.authentication.failure_handler.auth'] = $app->share(function ($app) {
    return new ChrDb\Security\AuthFailureHandler();
});

// Define a custom encoder for Security/Authentication
$app['security.encoder.digest'] = $app->share(function ($app) {
    // uses the password-compat encryption
    return new BCryptPasswordEncoder(10);
});

// Security definition.
$app->register(new SecurityServiceProvider(), array(
    'security.firewalls' => array(
        // Login URL is open to everybody.
        // 'login' => array(
        //      'pattern' => '^/api/login$',
        //      'anonymous' => true,
        //  ),
        // Any other URL requires auth.
        'auth' => array(
            //'pattern' => '^.*$',
            'pattern' => '^/api$',
            'form'      => array(
                'login_path'         => '/api/auth/login',
                'check_path'         => '/api/login',
                'username_parameter' => 'username',
                'password_parameter' => 'password'
            ),
            'logout'    => array('logout_path' => '/api/auth/logout'),
            'users'     => $app->share(function() use ($app) {
                return new ChrDb\Security\UserProvider($app);
            }),
        ),
    ),
));

$app['api.auth.controller'] = $app->share(function() use ($app) {
    return new ChrDb\Api\AuthController();
});
$app->get('/api/auth/login', "api.auth.controller:loginAction");
$app->get('/api/auth/logout', "api.auth.controller:logoutAction");

以下是相关代码的其余部分:

<?php 

namespace ChrDb\Security;

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
{
    public function __construct($app)
    {
        $this->app = $app;
    }

    public function loadUserByUsername($username)
    {
        $this->app['monolog']->addDebug('WTFFFF: ' . $username);
        $stmt = $this->app['db']->executeQuery("SELECT * FROM user WHERE username = ?", array(strtolower($username)));

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

        return new User($user['username'], $user['pwd_hash'], 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';
    }
}

<?php 

namespace ChrDb\Security;

use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class AuthSuccessHandler implements AuthenticationSuccessHandlerInterface
{
    /**
     * This is called when an interactive authentication attempt succeeds. This
     * is called by authentication listeners inheriting from
     * AbstractAuthenticationListener.
     *
     * @param Request        $request
     * @param TokenInterface $token
     *
     * @return Response never null
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        return new Response('Login was successful.', 200);
    }
}

<?php 


namespace ChrDb\Security;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;

class AuthFailureHandler implements AuthenticationFailureHandlerInterface
{
    /**
     * This is called when an interactive authentication attempt fails. This is
     * called by authentication listeners inheriting from
     * AbstractAuthenticationListener.
     *
     * @param Request                 $request
     * @param AuthenticationException $exception
     *
     * @return Response The response to return, never null
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        return new Response('Login failed.', 500);
    }
}

这是我在尝试调用 /api/login url 时遇到的错误: curl -d 'username=z@z.com&password=test' http://domain.com/api/login,以获取 200 或 401回复。

[2013-06-26 13:10:48] myapp.INFO: > POST /api/login [] []
[2013-06-26 13:10:48] myapp.CRITICAL: LogicException: The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller? (uncaught exception) at /Users/guachiman/Sites/chrdb/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php line 135 {"exception":"[object] (LogicException: The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller? at /Users/guachiman/Sites/chrdb/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php:135)"} []

有什么明显的我遗漏会导致此错误吗?我不知道它指的是哪个控制器返回 null。我觉得我可能需要设置我自己的整个自定义 ServiceProvider,但我希望只设置成功/失败处理程序就足够了。我很确定我只是对 login_path/check 路径有问题。

4

0 回答 0