Laravel5学生成绩管理系统-03-登陆登出功能-权限-中间件

可紊 提交于 2019-12-01 18:39:11


 这一节,我们完成登录登出的功能, 在路由中设置中间件, 过滤一些非法请求,关于中间件用户授权请参靠官方文档,如果是新手,强烈建议先看下文档然后再开始下面的工作。


#知识学习:

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的控制器中写需要的方法:

        
<?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

这个时候错误信息的右边就会有一个关闭按钮,点击就可隐藏错误信息

第二种带关闭提示错误信息的显示框:





易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!