Symfony security return 401 response instead of re

2020-02-20 01:05发布

问题:

I'm writing an ajax application with ajax authentication and now I started using the symfony security component in silex to handle authentication/authorization.
Doing a simple test with a simple configuration, I go to a protected area by the firewall and the response I get is a redirection to the /login page but what I need in my app is a 401 response with possible additional information(in headers or json body) on how to login.

$app['security.firewalls'] = [
    'api' => [
        'pattern' => '^/api',
        'logout' => ['logout_path'=>'/auth/logout'],
        'users' => $app->share(function(Application $app) {
            return new MyUserProvider();
        })
    ]
];

EDIT: I got a hint but I'm not sure how to use it. Implementing an entry point with AuthenticationEntryPointInterface I can tell the api how to answer unauthenticated requests and give the user the instructions needed to authenticate. That could be my 401 response with login instructions.

回答1:

What you need is a AuthenticationEntryPoint handler. Simple example:

class AuthenticationEntryPoint implements AuthenticationEntryPointInterface {

/**
 * Starts the authentication scheme.
 *
 * @param Request $request The request that resulted in an AuthenticationException
 * @param AuthenticationException $authException The exception that started the authentication process
 *
 * @return Response
 */
public function start(Request $request, AuthenticationException $authException = null)
{
    $array = array('success' => false);
    $response = new Response(json_encode($array), 401);
    $response->headers->set('Content-Type', 'application/json');

    return $response;
}
}

Register class as a service in services.xml file:

<parameters>
    <parameter key="authentication_entry_point.class">YourNameSpace\AuthenticationEntryPoint</parameter>
</parameters>

<services>
    <service id="authentication_entry_point" class="%authentication_entry_point.class%"/>
</services>

and make a small change in security.yml file:

security:
  firewalls:
    somename:
      entry_point: authentication_entry_point


回答2:

I was able to override the default entry point for the "form" type under the "api" firewall like this:

$app['security.entry_point.api.form'] = $app->share(function () use ($app) {
    return new MyAuthenticationEntryPoint();
});

Then it's just a matter of implementing the AuthenticationEntryPointInterface:

http://symfony.com/doc/current/components/security/firewall.html#entry-points

Have a look at the symfony implementation to get an idea:

Symfony\Component\Security\Http\EntryPoint\FormAuthenticationEntryPoint

Also, probably worth checking out the silex security service provider to see how they inject that into "security.entry_point.form._proto" the default implement.

Silex\Provider\SecurityServiceProvider