如何更改 Silex 中的安全重定向行为?

How do I change security redirect behavior in Silex?

如果我向安全区域发出 AJAX 请求,它会发送 302 header,然后重定向到该请求中的登录页面。有没有办法将防火墙配置为只提供不同的 header 而不是重定向?这是我需要在 ->before 调用中处理的事情吗?或者更好的方法是覆盖身份验证入口点,如 Symfony security return 401 response instead of redirect 中所建议的那样?那是针对 Symfony 的,所以不确定 Silex 是否有更好的糖分。

试过这个和其他东西:

$app->register(new SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'default' => array(
            'pattern' => '^/',
            'anonymous' => true,
            'oauth' => array(
                'failure_path' => '/login',
                'with_csrf' => true
            ),
            'logout' => array(
                'logout_path' => '/logout',
                'with_csrf' => true
            ),

        )
    ),

));

$app['security.authentication.entry_point.default.oauth'] = $app->share(function ($app) {
    return new AuthenticationEntryPointComponent();
});

$app['security.authentication.entry_point.default.form'] = $app->share(function ($app) {
    return new AuthenticationEntryPointComponent();
});

defaultsecurity.firewalls中的键名。仍然收到 302。

我不得不四处挖掘这么多代码,但明白了:

我的控制器:

$app['security.entry_point.form._proto'] =$app->protect(function ($name, array $options) use ($app) {
  return $app->share(function () use ($app, $options) {
      $login_path = isset($options['login_path']) ? $options['login_path'] : '/login';
      return new MyCustomClass($app['security.http_utils'], $login_path);
  });
});

class:

namespace Yours;

use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class MyCustomClass implements AuthenticationEntryPointInterface {

  protected $_login_path = '/login';

  protected $_http_tools;

  /**
   * @param string $loginPath  The path to the login form
   */
  public function __construct(HttpUtils $http_utils, $login_path = '') {
    $this->_http_tools = $http_utils;

    if ( $login_path ) {
      $this->_login_path = $login_path;
    }
  }

  /**
   * {@inheritDoc}
   */
  public function start(Request $request, AuthenticationException $authException = null) {
    if ($request->isXmlHttpRequest()) {
      $response = new Response(json_encode([]), 401);
      $response->headers->set('Content-Type', 'application/json');
      return $response;
    }

    return $this->_http_tools->createRedirectResponse($request, $this->_login_path);
  }

}

我也遇到了这个问题,令我惊讶的是 SecurityServiceProvider 不支持防火墙配置中的 entry_point 选项(就像 Symfony 安全配置一样)。

我用不同的方式解决了它。我没有覆盖 security.entry_point.form._proto,而是遵循 SecurityServiceProvider 内置身份验证工厂,在我的自定义服务提供商的 register() 中,我这样写:

$app['security.authentication_listener.factory.MY_CUSTOM_FIREWALL'] = $app->protect(function ($name, array $options) use ($app) {
    $app['security.authentication_provider.'.$name.'.anonymous'] = $app['security.authentication_provider.anonymous._proto']($name);
    $app['security.authentication_listener.'.$name.'.anonymous'] = $app['security.authentication_listener.anonymous._proto']($name, $options);
    $app['security.entry_point.'.$name.'.MY_CUSTOM_FIREWALL'] = $app->share(function() use ($app) {
        return new MyCustomFirewallEntryPoint($app['url_generator']);
    });

    return [
        'security.authentication_provider.'.$name.'.anonymous',
        'security.authentication_listener.'.$name.'.anonymous',
        'security.entry_point.'.$name.'.MY_CUSTOM_FIREWALL',
        'anonymous'
    ];
});

然后在安全配置中:

$app->register(new Silex\Provider\SecurityServiceProvider(), [
    'security.firewalls' => [
        // All other routes require valid user
        'secured' => [
            'pattern' => '^.*$',
            'anonymous' => true,
            // It will search for custom factory
            'MY_CUSTOM_FIREWALL' => true
        ],
    ],
]);