laravel自定义认证

laravel默认封装好了一个用户验证,但耦合度较高,比如对于多用户类型(admin,member,agent等)不支持,可以使用第三方类库如multiple auth,有时候可能只需要简单的后台认证,我们使用自己的方式认证可能更加快捷。

自行配置好数据库链接

模型

使用命令生成’Admin’模型以及对应的迁移

php artisan make:model Admin -m

如果单独创建迁移类文件,则使用:

php artisan make:migration create_admins_table --create=admins

数据库

编辑”/database/migrations/2015_10_26_085931_create_admins_table.php”迁移文件:

 public function up()
 {
 Schema::create('admins', function (Blueprint $table) {
 $table->increments('id');
 $table->string('username')->unique();
 $table->string('password', 60);
 $table->tinyInteger('level')->default(0);
 $table->tinyInteger('status')->default(0);
 $table->timestamps();
 });
 }

生成admins表:

php artisan migrate

向数据库中插入一条测试数据,附tinker简要使用方法:

>php artisan tinker
>>> $admin = new App\Admin
=> App\Admin {#717}
>>> $admin->username = 'test'
=> "test"
>>> $admin->password = bcrypt('test')
=> "$2y$10$kF75AzPfVm/6Bk5fNaEa1OstaHlaTzMygGn8vIeIKr7azLKmPmSz."
>>> $admin->save()
=> true

上述命令向表中插入了一条用户名密码均为’test’的数据。

在’app\Admin.php’模型中定义几个帮助方法:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
/**
 * App\Admin
 *
 * @property integer $id
 * @property string $username
 * @property string $password
 * @property \Carbon\Carbon $created_at
 * @property \Carbon\Carbon $updated_at
 * @method static \Illuminate\Database\Query\Builder|\App\Admin whereId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Admin whereUsername($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Admin wherePassword($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Admin whereCreatedAt($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Admin whereUpdatedAt($value)
 */
class Admin extends Model
{
 /**
 * 检查用户是否与数据库中匹配
 * @param $username 用户名
 * @param null $password 密码如果为空,则只检查数据库中是否存在该用户名
 * @return bool
 */
 static function _check($username, $password = null) {
 $where = ['username' => $username];
 $the_data = self::where($where)->first();
 if (count($the_data) < 1) {
 return false;
 }
 if (isset($password) && \Hash::check($password, $the_data->password)) {
 $ret = $the_data->toArray();
 unset($ret['password']);
 return $ret;
 }
 return false;
 }
/**
 * 判断是否登录
 * @return bool
 */
 static function _is_login() {
 return session('login_admin');
 }
/**
 * 登录
 * @param string $admin 要存储的值
 */
 static function _login($admin = '') {
 session(['login_admin' => $admin]);
 }
/**
 * 登出
 */
 static function _logout() {
 session()->forget('login_admin');
 }
}

中间件

这是一种规范,不是一种强制,比如也可以通过“BaseController”的思路来解决。

通过命令行创建“AdminAuth”中间件:

php artisan make:middleware AdminAuth

编辑”app\Http\Middleware\AdminAuth.php”中间件:

 public function handle($request, Closure $next)
 {
 if (!Admin::_is_login()) {
 return redirect('public/login');
 }
 return $next($request);
 }

编辑’app\Http\Kernel.php’,加入路由中间件:

'admin' => \App\Http\Middleware\AdminAuth::class,

路由

Route::group(['prefix' => 'admin', 'middleware' => 'admin'], function() {
 Route::get('/', function() {
 return 'This is home of admin';
 });
});
Route::group(['prefix' => 'public'], function() {
 Route::match(['get', 'post'], 'login', 'PublicController@login');
 Route::get('logout', 'PublicController@logout');
});

一个简单的路由,当访问”admin/*”的时候会自动加载’admin’的中间件。

控制器

创建’PublicController’控制器:

php artisan make:controller –plain

编辑’app\Http\Controllers\PublicController.php’:

<?php
namespace App\Http\Controllers;
use App\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class PublicController extends Controller
{
 function login(Request $request) {
 if ($request->isMethod('post')) {
 $input = $request->all();
 $rules = [
 'username' => 'required',
 'password' => 'required'
 ];
 $this->validate($request, $rules);
 if ($res = Admin::_check($input['username'], $input['password'])) { // 登录成功
 Admin::_login($res);
 return redirect('root');
 }
 return back()->withInput()->withErrors('登录失败');
 } else {
 return view('public.login');
 }
 }
function logout() {
 Admin::_logout();
 return redirect('public/login');
 }
}

视图

创建并编辑‘resources/views/public/login.blade.php’登录视图文件:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
 <title>用户登录</title>
 <meta charset="UTF-8">
 <meta name=description content="">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <!-- Bootstrap CSS -->
 <link href="{{ asset('bower_components/bootstrap/dist/css/bootstrap.min.css') }}" rel="stylesheet" media="screen">
</head>
<body>
 <div class="container">
 <div class="row">
 <div class="col-sm-4 col-sm-offset-4">
 <form method="post" class="form-horizontal" role="form">
 <div class="form-group {{ $errors->first('username')?'has-error':'' }}">
 <div class="col-xs-12">
 <input type="text" name="username" id="inputUsername" class="form-control" value="{{ old('username') }}" placeholder="用户名" autofocus />
 </div>
 </div>
 <div class="form-group {{ $errors->first('password')?'has-error':'' }}">
 <div class="col-xs-12">
 <input type="password" name="password" id="inputPassword" class="form-control" placeholder="密码" />
 </div>
 </div>
 <div class="form-group">
 <div class="col-xs-12">
 {{ csrf_field() }}
 <button type="submit" class="btn btn-primary btn-block">登录</button>
 </div>
 </div>
 </form>
 @if (count($errors) > 0)
 <div class="alert alert-danger">
 <ul class="list-unstyled">
 @foreach($errors->all() as $error)
 <li>{{ $error }}</li>
 @endforeach
 </ul>
 </div>
 @elseif(session('errors'))
 <div class="alert alert-danger">
 <ul class="list-unstyled">
 <li>{{ session('errors') }}</li>
 </ul>
 </div>
 @endif
 </div>
 </div>
 </div>
</body>
</html>