简体   繁体   中英

Laravel 5.1 Authentication for admin route

I'm new to Laravel and want to build a small admin area to create and edit data. I'm using the authentication which comes out of the box with Laravel 5.1 and followed this documentation http://laravel.com/docs/master/authentication .

I'm prefixing all my backend routes with "admin". Now, if I log in, I'm being redirected to the correct page. But once I click one link or reload the page, I'm being redirected to my login page.

I think I'm just getting something wrong with the routes...?

Additional info:

  • Laravel Framework version 5.1.17 (LTS)
  • I'm using vagrant as my dev environment. It's a custom box. But I already tried using Homestead with this file base, same problem.
  • Without the auth middleware, all my routes are accessible and are working properly.

routes.php

// Frontend
Route::get('/', ['as' => 'home', 'uses' => 'ContentController@index']);
Route::resource('comment', 'CommentController', ['only' => ['create','store']]);

// Authentication
Route::get('admin/login', array('as' => 'admin.login', 'uses' => 'Auth\AuthController@getLogin'));
Route::post('admin/login', array('as' => 'admin.login', 'uses' => 'Auth\AuthController@postLogin'));
Route::get('admin/logout', array('as' => 'admin.logout', 'uses' => 'Auth\AuthController@getLogout'));

// Backend Admin with Authentication
Route::group(array('prefix' => 'admin', 'middleware' => 'auth', 'namespace' => 'Admin'), function()
{
    Route::post('content/sortlist', ['as' => 'admin.content.sortlist', 'uses' => 'ContentController@sortList']);
    Route::resource('content', 'ContentController', ['except' => ['show']]);
    Route::resource('comment', 'CommentController', ['only' => ['index','destroy']]);
});

Output from php artisan route:list

+--------+----------+------------------------------+------------------------+-------------------------------------------------------+------------+
| Domain | Method   | URI                          | Name                   | Action                                                | Middleware |
+--------+----------+------------------------------+------------------------+-------------------------------------------------------+------------+
|        | GET|HEAD | /                            | home                   | App\Http\Controllers\ContentController@index          |            |
|        | GET|HEAD | admin/comment                | admin.comment.index    | App\Http\Controllers\Admin\CommentController@index    | auth       |
|        | DELETE   | admin/comment/{comment}      | admin.comment.destroy  | App\Http\Controllers\Admin\CommentController@destroy  | auth       |
|        | POST     | admin/content                | admin.content.store    | App\Http\Controllers\Admin\ContentController@store    | auth       |
|        | GET|HEAD | admin/content                | admin.content.index    | App\Http\Controllers\Admin\ContentController@index    | auth       |
|        | GET|HEAD | admin/content/create         | admin.content.create   | App\Http\Controllers\Admin\ContentController@create   | auth       |
|        | POST     | admin/content/sortlist       | admin.content.sortlist | App\Http\Controllers\Admin\ContentController@sortList | auth       |
|        | PATCH    | admin/content/{content}      |                        | App\Http\Controllers\Admin\ContentController@update   | auth       |
|        | DELETE   | admin/content/{content}      | admin.content.destroy  | App\Http\Controllers\Admin\ContentController@destroy  | auth       |
|        | PUT      | admin/content/{content}      | admin.content.update   | App\Http\Controllers\Admin\ContentController@update   | auth       |
|        | GET|HEAD | admin/content/{content}/edit | admin.content.edit     | App\Http\Controllers\Admin\ContentController@edit     | auth       |
|        | GET|HEAD | admin/login                  | admin.login            | App\Http\Controllers\Auth\AuthController@getLogin     | guest      |
|        | POST     | admin/login                  | admin.login            | App\Http\Controllers\Auth\AuthController@postLogin    | guest      |
|        | GET|HEAD | admin/logout                 | admin.logout           | App\Http\Controllers\Auth\AuthController@getLogout    |            |
|        | POST     | comment                      | comment.store          | App\Http\Controllers\CommentController@store          |            |
|        | GET|HEAD | comment/create               | comment.create         | App\Http\Controllers\CommentController@create         |            |
+--------+----------+------------------------------+------------------------+-------------------------------------------------------+------------+

app/Http/Controllers/Auth/AuthController.php

<?php

namespace App\Http\Controllers\Auth;

use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;

class AuthController extends Controller
{

    /*
    |--------------------------------------------------------------------------
    | Registration & Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users, as well as the
    | authentication of existing users. By default, this controller uses
    | a simple trait to add these behaviors. Why don't you explore it?
    |
    */

    use AuthenticatesAndRegistersUsers, ThrottlesLogins;

    protected $redirectPath = 'admin/content';

    protected $loginPath = 'admin/login';

    /**
     * Create a new authentication controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest', ['except' => 'getLogout']);
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'firstname' => 'required|max:255',
            'lastname' => 'required|max:255',
            'email' => 'required|email|max:255|unique:users',
            'password' => 'required|confirmed|min:6',
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return User
     */
    protected function create(array $data)
    {
        return User::create([
            'firstname' => $data['firstname'],
            'lastname' => $data['lastname'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }
}

app/Http/Middleware/Authenticate.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Auth\Guard;

class Authenticate
{
    /**
     * The Guard implementation.
     *
     * @var Guard
     */
    protected $auth;

    /**
     * Create a new filter instance.
     *
     * @param  Guard  $auth
     * @return void
     */
    public function __construct(Guard $auth)
    {
        $this->auth = $auth;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($this->auth->guest()) {
            if ($request->ajax()) {
                return response('Unauthorized.', 401);
            } else {
                return redirect()->guest('admin/login');
            }
        }

        return $next($request);
    }
}

app/Http/Middleware/RedirectIfAuthenticated.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Auth\Guard;

class RedirectIfAuthenticated
{
    /**
     * The Guard implementation.
     *
     * @var Guard
     */
    protected $auth;

    /**
     * Create a new filter instance.
     *
     * @param  Guard  $auth
     * @return void
     */
    public function __construct(Guard $auth)
    {
        $this->auth = $auth;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($this->auth->check()) {
            return redirect('admin/content');
        }

        return $next($request);
    }
}

postLogin at vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php (changed nothing here)

<?php

namespace Illuminate\Foundation\Auth;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;

trait AuthenticatesUsers
{
    use RedirectsUsers;

    /**
     * Show the application login form.
     *
     * @return \Illuminate\Http\Response
     */
    public function getLogin()
    {
        if (view()->exists('auth.authenticate')) {
            return view('auth.authenticate');
        }

        return view('auth.login');
    }

    /**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function postLogin(Request $request)
    {
        $this->validate($request, [
            $this->loginUsername() => 'required', 'password' => 'required',
        ]);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        $throttles = $this->isUsingThrottlesLoginsTrait();

        if ($throttles && $this->hasTooManyLoginAttempts($request)) {
            return $this->sendLockoutResponse($request);
        }

        $credentials = $this->getCredentials($request);

        if (Auth::attempt($credentials, $request->has('remember'))) {
            return $this->handleUserWasAuthenticated($request, $throttles);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        if ($throttles) {
            $this->incrementLoginAttempts($request);
        }

        return redirect($this->loginPath())
            ->withInput($request->only($this->loginUsername(), 'remember'))
            ->withErrors([
                $this->loginUsername() => $this->getFailedLoginMessage(),
            ]);
    }

    /**
     * Send the response after the user was authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  bool  $throttles
     * @return \Illuminate\Http\Response
     */
    protected function handleUserWasAuthenticated(Request $request, $throttles)
    {
        if ($throttles) {
            $this->clearLoginAttempts($request);
        }

        if (method_exists($this, 'authenticated')) {
            return $this->authenticated($request, Auth::user());
        }

        return redirect()->intended($this->redirectPath());
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function getCredentials(Request $request)
    {
        return $request->only($this->loginUsername(), 'password');
    }

    /**
     * Get the failed login message.
     *
     * @return string
     */
    protected function getFailedLoginMessage()
    {
        return Lang::has('auth.failed')
                ? Lang::get('auth.failed')
                : 'These credentials do not match our records.';
    }

    /**
     * Log the user out of the application.
     *
     * @return \Illuminate\Http\Response
     */
    public function getLogout()
    {
        Auth::logout();

        return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
    }

    /**
     * Get the path to the login route.
     *
     * @return string
     */
    public function loginPath()
    {
        return property_exists($this, 'loginPath') ? $this->loginPath : '/auth/login';
    }

    /**
     * Get the login username to be used by the controller.
     *
     * @return string
     */
    public function loginUsername()
    {
        return property_exists($this, 'username') ? $this->username : 'email';
    }

    /**
     * Determine if the class is using the ThrottlesLogins trait.
     *
     * @return bool
     */
    protected function isUsingThrottlesLoginsTrait()
    {
        return in_array(
            ThrottlesLogins::class, class_uses_recursive(get_class($this))
        );
    }
}

How I link to admin pages in my master.admin blade file (maybe that's the culprit?)

<ul class="nav nav-sidebar">
<li {{ Request::is('admin/content') ? "class=active" : null }}><a href="{{ URL::route('admin.content.index') }}">Inhalte <span class="sr-only">(current)</span></a></li>
<li {{ Request::is('admin/comment') ? "class=active" : null }}><a href="{{ URL::route('admin.comment.index') }}">Kommentare <span class="sr-only">(current)</span></a></li>
</ul>

Following countless google links, I already checked the storage/framework/sessions directory permissions and checked if the session is persistent. Seems so to me. I switched from file based session to database session in config/session.php, no change at all. There's nothing in the laravel.log file either.

I'm at my wits' end. Probably it's just some configuration I just don't get.

Thanks for your help!

Found the solution. I stumbled over a different question here on stackoverflow regarding auth and found the problem.

I used

<li><a href="{{ Auth::logout() }}">Logout</a></li>

in my blade template to logout. As long as this was present, the above described behaviour would appear. I replaced it with the following

<li><a href="{{ URL::to('admin/logout') }}">Logout</a></li>

and now everything works as expected! I'd still like to know why this happens... But maybe this will help someone else!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM