Laravel 4 Basic Auth custom error

心已入冬 提交于 2019-12-08 14:02:26

Basic Auth

Try to capture 401 error and return cusom view?!

App::error(function($exception, $code)
{
    switch ($code)
    {
        case 401:
            return Response::view('errors.403', array(), 401);

        case 403:
            return Response::view('errors.403', array(), 403);

        case 404:
            return Response::view('errors.404', array(), 404);

        case 500:
            return Response::view('errors.500', array(), 500);

        default:
            return Response::view('errors.default', array(), $code);
    }
});





Using Auth library

I think, code is pretty straightforward and self explaining. Just to note, $errors variable is of type MessageBag and is available in views even if you don't set it explicitly! Which is great! :)

I used simple routing, place it into your controllers

app/routes.php

Route::get('auth', function()
{
    $creds = array(
        'email' => Input::get('email'),
        'password'  => Input::get('password'),
    );

    if ( ! Auth::attempt($creds))
    {
        $errors = new MessageBag;
        $errors->add('login', trans("Username and/or password invalid."));
        return Redirect::to('/')->withErrors($errors);
    }

    return Redirect::to('/protected/area');

});


Route::get('/', function(){
    return View::make('hello');
});



// app/views/hello.php
@if($errors->has('login'))
    {{ $errors->first('login') }}
@endif

Here's how I did it:

Route::filter('auth.basic', function()
{
    $message = [
        "error" => [
            "code" => 401,
            "message" => "Invalid Credentials"
        ]
    ];

    $headers = ['WWW-Authenticate' => 'Basic'];

    $response = Auth::basic();

    if (!is_null($response)) {

        return Response::json($message, 401, $headers);
    }
});

If you look in Illuminate\Auth\Guard you'll find the basic method that's called by Auth::basic(). It either returns null or a Response object via the getBasicResponse method.

/**
 * Attempt to authenticate using HTTP Basic Auth.
 *
 * @param  string  $field
 * @param  \Symfony\Component\HttpFoundation\Request  $request
 * @return \Symfony\Component\HttpFoundation\Response|null
 */
public function basic($field = 'email', Request $request = null)
{
    if ($this->check()) return;

    $request = $request ?: $this->getRequest();

    // If a username is set on the HTTP basic request, we will return out without
    // interrupting the request lifecycle. Otherwise, we'll need to generate a
    // request indicating that the given credentials were invalid for login.
    if ($this->attemptBasic($request, $field)) return;

    return $this->getBasicResponse();
}

Here's getBasicResponse:

/**
 * Get the response for basic authentication.
 *
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function getBasicResponse()
{
    $headers = array('WWW-Authenticate' => 'Basic');

    return new Response('Invalid credentials.', 401, $headers);
}

Here we finally have our 'Invalid credentials.' text that we're looking to change. We see it's just returning an instance of a Symphony response with a 401 status code and the Basic Auth header and null in all other occasions. So, we'll just check for a non-null result and if we get one, return our new response as shown above.

Also, if you want it to actually be stateless you should use:

Auth::onceBasic()

I don't know how future proof this method is, but it works as of Laravel 4.1.

Final results once again:

Route::filter('auth.basic', function()
{
    $message = [
        "error" => [
            "code" => 401,
            "message" => "Invalid Credentials"
        ]
    ];

    $headers = ['WWW-Authenticate' => 'Basic'];

    $response = Auth::onceBasic();

    if (!is_null($response)) {

        return Response::json($message, 401, $headers);
    }
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!