laravel框架學習之路(一)先後臺用戶認證分離

準備工做:
一、下載laravel框架
二、配置好項目(數據庫鏈接以及虛擬主機)php

開始:
前臺用戶認證laravel已經爲咱們寫好了,此部分可參考官方文檔laravel

建立模型(以adminstrator爲例)web

php artisan make:model Models/Adminstrator -m

編寫administrator表遷移數據庫

Schema::create('administrators', function (Blueprint $table) {
    $table->engine = 'InnoDB';
    $table->increments('id');
    $table->string('login_name')->unique();
    $table->string('display_name')->nullable();
    $table->string('password');
    $table->string('avatar')->nullable();
    $table->rememberToken();
    $table->tinyInteger('status')->default(1);
    $table->timestamps();
});

編寫administrator模型數組

<?php

namespace App\Models;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;

class Administrator extends Model implements AuthenticatableContract
{
    use Authenticatable;

    protected $fillable = [
        'login_name', 'password'
    ];

    protected $hidden = [
        'password', 'remember_token'
    ];
}

建立後臺配置文件admin.php,在return數組中寫入session

'auth' => [
    'guards' => [
        'administrator' => [
            'driver'   => 'session',
            'provider' => 'administrators',
        ],
    ],

    'providers' => [
        'administrators' => [
            'driver' => 'eloquent',
            'model'  => \App\Models\Administrator::class,
        ],
    ],
],

建立後臺用戶認證中間件Authenticate,運行:app

php artisan make:middleware Admin/Authenticate

修改handle方法:框架

<?php

/**
 * 用戶認證中間件
 */

namespace App\Http\Middleware\Admin;

use Closure;
use Illuminate\Support\Facades\Auth;
    
class Authenticate
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (Auth::guard('administrator')->guest() && !$this->shouldPassThrough($request)) {
            return redirect()->guest(admin_base_path('login'));
        }
        return $next($request);
    }

    /**
     * Determine if the request has a URI that should pass through verification.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return bool
     */
    protected function shouldPassThrough($request)
    {
        $excepts = [
            admin_base_path('login'),
            admin_base_path('logout'),
        ];
        foreach ($excepts as $except) {
            if ($except !== '/') {
                $except = trim($except, '/');
            }
            if ($request->is($except)) {
                return true;
            }
        }
        return false;
    }
}

建立AdminServiceProvider,運行:ide

php artisan make:provider AdminServiceProvider

編寫:函數

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AdminServiceProvider extends ServiceProvider
{
    /**
     * 路由中間件
     * @var array
     */
    protected $routeMiddleware = [
        'admin.auth' => \App\Http\Middleware\Admin\Authenticate::class,
        'admin.pjax' => \Spatie\Pjax\Middleware\FilterIfPjax::class,
        'admin.log' => \App\Http\Middleware\Admin\LogOperation::class,
    ];

    /**
     * 中間件組
     * @var array
     */
    protected $middlewareGroups = [
        'admin' => [
            'admin.auth',
            'admin.pjax',
            'admin.log',
        ],
    ];

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        if (file_exists($routes = base_path('routes/admin.php'))) {
            $this->loadRoutesFrom($routes);
        }
    }

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->loadAdminAuthConfig();

        $this->registerRouteMiddleWare();
    }

    /**
     * 註冊路由中間件
     */
    public function registerRouteMiddleWare()
    {
        // 註冊路由中間件
        foreach ($this->routeMiddleware as $key => $middleware) {
            app('router')->aliasMiddleware($key, $middleware);
        }

        // 註冊路由中間件組
        foreach ($this->middlewareGroups as $key => $middleware) {
            app('router')->middlewareGroup($key, $middleware);
        }
    }

    /**
     * Setup auth configuration.
     *
     * @return void
     */
    protected function loadAdminAuthConfig()
    {
        config(array_dot(config('admin.auth', []), 'auth.'));
    }
}

config/app.php中註冊provider和facades

'providers' => [
    ...,
    App\Providers\AdminServiceProvider::class,
]

'aliases' => [
    ...,
    'Admin' => App\Facades\Admin\Admin::class,
]

建立登陸表單驗證類,運行:

php artisan make:request AdministratorLoginRequest

重寫其父類rulesmessages方法:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class AdministratorLoginRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'login_name' => 'required',
            'password' => ['required', 'min:6'] //密碼必須,最小長度爲6
        ];
    }

    public function messages()
    {
        return [
            'login_name.required' => '請輸入用戶名',
            'password.required' => '請輸入密碼',
            'password.min' => '密碼至少6位',
        ];
    }
}

建立登陸控制器,運行:

php artisan make:controller Admin/Auth/LoginController

編寫登陸方法:

<?php

namespace App\Http\Controllers\Admin\Auth;

use App\Http\Requests\AdministratorLoginRequest;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /**
     * 登陸表單
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function getLoginForm()
    {
        if (!Auth::guard('administrator')->guest()) {
            return redirect(config('admin.route.prefix'));
        }

        return view(admin_view_base_path('auth.login.index'));
    }

    /**
     * 登陸操做
     * @param AdministratorLoginRequest $loginRequest
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function postLogin(AdministratorLoginRequest $loginRequest)
    {
        $postData = $loginRequest->only('login_name', 'password', 'remember');

        $result = Auth::guard('administrator')->attempt($postData, $loginRequest->filled('remember'));

        if ($result) {
            admin_toast('登陸成功');
            $loginRequest->session()->regenerate();
            return redirect()->intended(config('admin.route.prefix'));
        }else{
            return redirect()->back()->withInput()
                ->withErrors([
                    'login_name' => '用戶名或密碼錯誤'
                ]);
        }
    }

    /**
     * 註銷登陸
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function postLogout()
    {
        Auth::guard('administrator')->logout();

        session()->forget('url.intented');

        return redirect(config('admin.route.prefix'));
    }
}

至此,認證業務已經完成,接下來進行完善,使系統可以跑起來

建立視圖文件(ps:一、控制器中使用的admin_view_base_path爲自定義函數,指向後臺視圖文件主目錄。二、視圖採用AdminLTE框架)
login.blade:form

<form action="{{ admin_base_path('login') }}" method="post">
            @csrf

            <div class="form-group has-feedback">
                <input type="text" class="form-control {{ $errors->has('login_name') ? ' is-invalid' : '' }}"
                       placeholder="登 錄 名" name="login_name" value="{{ old('login_name') }}" required autofocus>
                <span class="glyphicon glyphicon-envelope form-control-feedback"></span>

                @if ($errors->has('login_name'))
                <span class="invalid-feedback">
                    <strong class="text-danger">{{ $errors->first('login_name') }}</strong>
                </span>
                @endif
            </div>

            <div class="form-group has-feedback">
                <input type="password" class="form-control {{ $errors->has('password') ? ' is-invalid' : '' }}"
                       placeholder="密 碼" name="password" required>
                <span class="glyphicon glyphicon-lock form-control-feedback"></span>

                @if ($errors->has('password'))
                    <span class="invalid-feedback">
                        <strong class="text-danger">{{ $errors->first('password') }}</strong>
                    </span>
                @endif
            </div>

            <div class="row">
                <div class="col-xs-8">
                    <div class="checkbox icheck">
                        <label>
                            <input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> 記住我
                        </label>
                    </div>
                </div>

                <!-- /.col -->
                <div class="col-xs-4">
                    <button type="submit" class="btn btn-primary btn-block btn-flat">登 錄</button>
                </div>
                <!-- /.col -->
            </div>
        </form>

建立後臺home控制器,運行:

php artisan make:controller Admin/Home/HomeController

編寫index方法返回視圖

<?php

namespace App\Http\Controllers\Admin\Home;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class HomeController extends Controller
{
    //
    public function index()
    {
        return view(admin_view_base_path('home.index'));
    }

}

若僅做登陸以後跳轉測試,home視圖中保留註銷按鈕便可,例:
home.blade

<div class="pull-right">
    <a class="btn btn-default btn-flat" href="/admin/logout"
       onclick="event.preventDefault();
                         document.getElementById('logout-form').submit();">
        {{ __('注 銷') }}
    </a>
</div>

<form id="logout-form" class="hide" action="{{ admin_base_path('logout') }}" method="POST" style="display: none;">
    @csrf
</form>

編輯配置文件config.admin.php,加入如下配置:

'route' => [
    'prefix' => 'admin',

    'namespace' => 'App\\Http\\Controllers\\Admin',

    'middleware' => ['web', 'admin'],
],

編寫路由文件routes/admin.php

<?php

use Illuminate\Routing\Router

Route::group([
    'prefix'        => config('admin.route.prefix'),
    'namespace'     => config('admin.route.namespace'),
    'middleware'    => config('admin.route.middleware'),
], function (Router $router) {
    $router->get('/', 'Home\HomeController@index');
    $router->get('login', 'Auth\LoginController@getLoginForm');
    $router->post('login', 'Auth\LoginController@postLogin');
    $router->post('logout', 'Auth\LoginController@postLogout');
});

數據表遷移與填充: 修改database/seeds/DatabaseSeeder

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        DB::table('administrators')->insert(
            [
                'login_name' => 'admin',
                'display_name' => '超級管理員',
                'password' => bcrypt('123456'),
                'created_at' => date('Y-m-d H:i:s', time()),
                'updated_at' => date('Y-m-d H:i:s', time()),
            ]
        );
    }
}

運行:

php artisan migrate //數據表遷移
php artisan db:seed //數據填充

若是前臺使用了laravel框架用戶認證的話,須要重寫框架生成的LoginControllerlogout方法。防止前臺用戶註銷的時候清除後臺用戶的session。(ps:框架自帶用戶認證在註銷時會清空全部session)

/**
 * 重寫前臺註銷操做
 * @param Request $request
 * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
 */
public function logout(Request $request)
{
    $this->guard()->logout();

    $request->session()->forget('uri.intented');

    return redirect('/');
}

至此,後臺用戶登陸所有完成。enjoy it!

相關文章
相關標籤/搜索