douhuangzhi0707 2015-10-01 08:57
浏览 116
已采纳

Laravel 5.1管理员路由的身份验证

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!

  • 写回答

1条回答 默认 最新

  • donglian2106 2015-10-02 08:59
    关注

    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!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用三极管设计—个共射极放大电路
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示