Laravel5學生成績管理系統-03-登錄登出功能-權限-中間件


php

 這一節,咱們完成登陸登出的功能, 在路由中設置中間件, 過濾一些非法請求,關於中間件用戶受權請參靠官方文檔,若是是新手,強烈建議先看下文檔而後再開始下面的工做。css


#知識學習:html

HTTP 中間件

HTTP 中間件提供了一個方便的機制來過濾進入應用程序的 HTTP 請求,例如,Laravel 自己使用中間件來驗證用戶的身份,若是用戶未經過身份驗證,中間件將會把用戶導向登陸頁面,反之,當用戶經過了身份驗證,中間件將會經過此請求並接着往下執行。laravel

固然,除了身份驗證以外,中間件也能夠被用來運行各式各樣的任務,CORS 中間件負責替全部即將離開程序的響應加入適當的標頭。而日誌中間件則能夠記錄全部傳入應用程序的請求。git

Laravel 框架已經內置了一些中間件,包括維護、身份驗證、CSRF 保護,等等。全部的中間件都放在app/Http/Middleware 目錄內。ajax

註冊中間件#

全局中間件#

如果但願每一個 HTTP 請求都通過一箇中間件,只要將中間件的類加入到 app/Http/Kernel.php 的 $middleware 屬性清單列表中。json

爲路由指派中間件#

若是你要指派中間件給特定路由,你得先在 app/Http/Kernel.php 給中間件設置一個好記的鍵,默認狀況下,這個文件內的 $routeMiddleware 屬性已包含了 Laravel 目前設置的中間件,你只須要在清單列表中加上一組自定義的鍵便可。bootstrap

// 在 App\Http\Kernel 類內...
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,];

中間件一旦在 HTTP kernel 文件內被定義,便可在路由選項內使用 middleware 鍵值指定:數組

Route::get('admin/profile', ['middleware' => 'auth', function () {
    //}]);


項目實戰:app

先看routes.php的登錄登出的路由:

     
##############
### 登錄登出功能
##############
Route::get('login', [
    // 'uses' :表示指定路由名稱到控制器動做
    'middleware' => 'guest', 'as'=>'login', 'uses' => 'loginController@LoginGet'
]);
Route::post('login', [
    'middleware' => 'guest', 'uses' => 'loginController@LoginPost'
]);
Route::get('logout', [
    'middleware' => 'auth', 'as'=>'logout', 'uses' => 'loginController@Logout'
]);


guest 只容許遊客(沒登錄的狀況下)訪問get路由login和post路由login,要是已經登陸,就會跳轉到相應頁面,注意關鍵詞響應。咱們登陸用戶有兩種,學生,和管理員,當他們在登陸的狀況下要想訪問這兩個路由,確定會作出不一樣的響應。即,學生,跳轉到學生主頁,管理員,跳轉到管理員主頁.如今來看看RedirectIfAuthenticated.php

      
/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if ($this->auth->check()) // 用戶是否登錄
    {
        if(!Auth::user()->is_admin){
            return new RedirectResponse('/stu/home');  // 不是管理員
        }else{
            return new RedirectResponse(url('/admin'));  // 若是是管理員,則進入後臺管理頁面
        }

    }

    return $next($request);
}


  auth 只有登陸用戶才能訪問,auth是在Kernel.php中註冊的全局中間件

'auth' => \App\Http\Middleware\Authenticate::class,


 咱們能夠看下源碼 Authenticate.php

   
/**
 * 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())  // 經過ajax來請求,這裏返回json數據
        {
            return response('Unauthorized.', 401);
        }
        else  // 直接請求, 跳轉到登陸頁
        {
            return redirect()->guest('auth/login');
        }
    }

    return $next($request);
}


也就是說只有登陸了才能登出,就是這個意思。

說完了中間件,建立控制器。loginController.php

php artisan make:controller loginController --plain


在loginController.php的控制器中寫須要的方法:

        
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;
// 引入用戶類
use App\UsersInfo;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;

class loginController extends Controller
{
    /**
     * 返回login視圖,登錄頁面
     */
    public function loginGet()
    {
        return view('login');
    }

    /**
     * 登錄響應
     */
    public function loginPost(Request $request)
    {
        // 登陸驗證規則
        $this->validate($request, UsersInfo::rules());
        $id = $request->get('id');
        $password = $request->get('password');
        if(Auth::attempt(['id' => $id, 'password' => $password], $request->get('remember')))
        {
            if(!Auth::user()->is_admin){
                return Redirect::route('stu_home');
            }else {
                return Redirect::action('Admin\AdminController@index');
            }
        }else{
            return Redirect::route('login')
                ->withInput()
                ->withErrors('學號或者密碼不正確,請重試!');
        }

    }

    /**
     * 用戶登出
     */
    public function logout()
    {
        if (Auth::check()) {
            Auth::logout();
        }
        return Redirect::route('login');
    }

}


可使用validate驗證用戶輸入,在laravel5中使用validate很是方便,注意第二個參數,User::rules(), 這是在User模型中一個靜態方法,接着在User.php中加入靜態方法。

protected static function rules()
{
    return [
        'id' => 'required|digits:10',   <!-- 表明必需填寫,10位數字 -->
        'password' => 'required'        <!-- 必填 -->
        ];
}

驗證用戶登陸使用了Auth::attempt(),這是laravel中自帶的驗證方法,很是好用,若是驗證經過,接着判斷是不是管理員,而後分別跳轉到不一樣的url.

return Redirect::route('stu_home') -- 對應路由名爲stu_home的路由
return Redirect::action('Admin\AdminController@index') -- 對於這個index方法

登出使用的是Auth::logout().

這時候點擊登陸,laravel會告訴你view(login)不存在,建立login.blade.php文件

     
@extends('master')

@section('title')
    歡迎登陸
@stop

@section('content')
<div class="container-fluid">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">登陸</div>
                <div class="panel-body">

                    @include('errors.list')

                    {!! Form::open(['url' => '/login', 'class' => 'form-horizontal', 'role' => 'form']) !!}
                        <div class="form-group">
                            {!! Form::label('id', '學號', ['class' => 'col-md-4 control-label']) !!}
                            <div class="col-md-6">
                                {!! Form::text('id', old('id'), ['class' => 'form-control', 'required']) !!}
                            </div>
                        </div>
                        <div class="form-group">
                            {!! Form::label('password', '密碼', ['class' => 'col-md-4 control-label']) !!}
                            <div class="col-md-6">
                                {!! Form::password('password', ['class' => 'form-control', 'required']) !!}
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <div class="checkbox">
                                    <label>
                                        <input type="checkbox" name="remember"> Remember Me
                                    </label>
                                </div>
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                {!! Form::submit('Login', ['class' => 'btn btn-primary form-control']) !!}
                            </div>
                        </div>
                    {!! Form::close() !!}
                </div>
            </div>
        </div>
    </div>
</div>
@stop


這時候要是點擊登陸,若是報錯,由於在laravel5中Illuminate/Html組件被移了,咱們能夠在composer.json的required數組中加入

"illuminate/html": "5.0"

在config/app.php中的provider數組中添加

'Illuminate\Html\HtmlServiceProvider',

aliases數組中添加

'Html'      => 'Illuminate\Html\HtmlFacade',
'Form'      => 'Illuminate\Html\FormFacade',

接着執行:

composer update

等待安裝完成以後,就能看到咱們的登陸頁面了

這時候你隨便輸入學號密碼,頁面會刷新一下,不會跳轉,錯誤已經被存在了Session中,如今把他顯示出來. 在login.blade.php中有這樣一行

@include('errors.list')

咱們建立errors/list.blade.php

@if (count($errors) > 0)
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

這時候要是輸入不符合前面的規則,你會看到提示英文提示信息,要是輸入密碼或者賬號錯誤,你會看到 學號或者密碼不正確,請重試, 這是loginPost中返回的自定義錯誤信息.

如今,咱們有兩個問題須要解決,第一,英文提示信息,對咱們中國用戶可能不太友好,你能夠更換.第二,錯誤提示會一直留着頁面.下面,咱們一一解決.

關於表單驗證的自定義錯誤信息,能夠查看官方連接, 如今咱們找到/resources/lang/en/validation.php,在custom數組中添加:

'id' => [
        'required' => '學號不能爲空',
        "digits"   => "學號必須是 10 位數字",
        "unique"   => "該同窗已經存在",
    ],
'password' => [
        'required' => '密碼不能爲空',
    ],

從新隨便輸入學號密碼,你就能夠看到中文提示信息了

關於提示信息的隱藏,這裏有兩種簡單的解決方案,參靠bootstrap中的警告框,修改/errors/list.blade.php

@if (count($errors) > 0)
    <div class="alert alert-danger alert-dismissible" role="alert">
        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

這個時候錯誤信息的右邊就會有一個關閉按鈕,點擊就可隱藏錯誤信息

第二種帶關閉提示錯誤信息的顯示框:

相關文章
相關標籤/搜索