如何捕获 Silex 中的身份验证错误?

How to catch authentication errors in Silex?

我正在使用 Silex 框架开发 Rest API,我使用 SecurityServiceProvider。但是,如果用户发送错误的凭据并抛出 HTTP,我不知道如何捕获错误以显示如下内容:

{"status_code":401, "error_message":"Bad credentials"}

下面是我的部分代码:

$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'default' => array(
            'pattern' => '^.*$',
            'stateless' => true,
            'http' => true,
            'users' => $app->share(function() use ($app) {
                return new App\Providers\UserProvider($app['db']);
            }),
        ),
    ),
));

// ...

$app->error(function (\Exception $e, $code) use ($app) {
    // This code is never executed in case of Bad credentials

    // ...

    return new JsonResponse($contentResponse, $statusCode);
});

提前致谢

编辑

我知道我可以使用 $app['security.authentication.failure_handler.'.$name],但在我的案例中从未处理过。

$app['security.authentication.failure_handler.default'] = $app->share(function ($app) {
     // This code is never executed
     return new MySuccessHandler();
});

是因为'http' => true吗?

试试

$app->error(function (\Exception $e, $code) use ($app) {
   // This code is never executed in case of Bad credentials

   if($e instanceof AuthenticationException){

       return new JsonResponse(["status_code"=>401, "error_message"=>"Bad credentials"], 401);
   }
   // ...

  return new JsonResponse($contentResponse, $statusCode);
});

而不是使用通用的 error 函数,您可以听 the security events emitted by the security component,特别是 security.authentication.failure 一个。

为此,您只需调用 on 方法:

<?php

use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent

//...
$app->on('security.authentication.failure', function(AuthenticationFailureEvent $event) {
  // you can do some checks if you want, but there's no need...

  return new JsonResponse($contentResponse, $statusCode);
});

请记住,这是未经测试的代码。

由于我的代码结构,我决定检查after中间件中的错误,抛出异常并用$app->error(...)捕获它。

$app->after(function (Request $request, Response $response) {
    // If Unauthorized
    if ($response->getStatusCode() == 401)
        throw new Exception('Unauthorized'); // This exception will be handled by "$app->error(...)"
});


$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'default' => array(
            'pattern' => '^.*$',
            'stateless' => true,
            'http' => true,
            'users' => $app->share(function() use ($app) {
                return new App\Providers\UserProvider($app['db']);
            }),
        ),
    ),
));

// ...

$app->error(function (\Exception $e, $code) use ($app) {
    // ...
    return new JsonResponse($contentResponse, $statusCode);
});