这一节,我们完成登录登出的功能, 在路由中设置中间件, 过滤一些非法请求,关于、请参靠官方文档,如果是新手,强烈建议先看下文档然后再开始下面的工作。
#知识学习:
HTTP 中间件
HTTP 中间件提供了一个方便的机制来过滤进入应用程序的 HTTP 请求,例如,Laravel 本身使用中间件来验证用户的身份,如果用户未通过身份验证,中间件将会把用户导向登录页面,反之,当用户通过了身份验证,中间件将会通过此请求并接着往下执行。
当然,除了身份验证之外,中间件也可以被用来运行各式各样的任务,CORS 中间件负责替所有即将离开程序的响应加入适当的标头。而日志中间件则可以记录所有传入应用程序的请求。
Laravel 框架已经内置了一些中间件,包括维护、身份验证、CSRF 保护,等等。所有的中间件都放在app/Http/Middleware
目录内。
全局中间件
若是希望每个 HTTP 请求都经过一个中间件,只要将中间件的类加入到 app/Http/Kernel.php
的 $middleware
属性清单列表中。
为路由指派中间件
如果你要指派中间件给特定路由,你得先在 app/Http/Kernel.php
给中间件设置一个好记的键,默认情况下,这个文件内的 $routeMiddleware
属性已包含了 Laravel 目前设置的中间件,你只需要在清单列表中加上一组自定义的键即可。
// 在 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 () { //}]);
项目实战:
先看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的控制器中写需要的方法:
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', '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')登录@include('errors.list') {!! Form::open(['url' => '/login', 'class' => 'form-horizontal', 'role' => 'form']) !!}{!! Form::label('id', '学号', ['class' => 'col-md-4 control-label']) !!}{!! Form::text('id', old('id'), ['class' => 'form-control', 'required']) !!}{!! Form::label('password', '密码', ['class' => 'col-md-4 control-label']) !!}{!! Form::password('password', ['class' => 'form-control', 'required']) !!}{!! Form::submit('Login', ['class' => 'btn btn-primary form-control']) !!} {!! Form::close() !!} @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)@foreach ($errors->all() as $error)
@endif- { { $error }}
@endforeach
这时候要是输入不符合前面的规则,你会看到提示英文提示信息,要是输入密码或者帐号错误,你会看到 学号或者密码不正确,请重试, 这是loginPost中返回的自定义错误信息.
现在,我们有两个问题需要解决,第一,英文提示信息,对我们中国用户可能不太友好,你可以更换.第二,错误提示会一直留着页面.下面,我们一一解决.
关于表单验证的自定义错误信息,可以查看, 现在我们找到/resources/lang/en/validation.php,在custom数组中添加:
'id' => [ 'required' => '学号不能为空', "digits" => "学号必须是 10 位数字", "unique" => "该同学已经存在", ],'password' => [ 'required' => '密码不能为空', ],
重新随便输入学号密码,你就可以看到中文提示信息了
关于提示信息的隐藏,这里有两种简单的解决方案,参靠bootstrap中的,修改/errors/list.blade.php
@if (count($errors) > 0)
这个时候错误信息的右边就会有一个关闭按钮,点击就可隐藏错误信息
第二种带关闭提示错误信息的显示框: