欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

20150720-Laravel登录验证碰到的坑

shiping1 的头像
录踩过的坑,以后的坑就会越来越少……

首先 建表:

php artisan migrate:make_admin_table

然后在新建的文件里面写上表的各列设置

<?phpuse Illuminate/Database/Schema/Blueprint;use Illuminate/Database/Migrations/Migration;class CreateAdminTable extends Migration {    /**     * Run the migrations.     *     * @return void     */    public function up()    {        Schema::create('admin', function($table)        {            $table->increments('id');            $table->string('staff_code', 32)->nullable();           //员工号            $table->string('login_name', 32)->nullable();           //登录名            $table->string('password', 32)->nullabele();            //登录密码            $table->string('mail', 512)->nullable();                //电子邮箱            $table->string('staff_name', 32)->nullable();           //员工姓名            $table->string('sex', 10)->nullable();                  //性别            $table->string('belong_to', 512)->nullable();           //所属部门            $table->string('jobs', 512)->nullable();                //岗位            $table->string('telephone', 32)->nullable();            //固定电话            $table->string('mobile', 32)->nullable();               //手机号        });    }    /**     * Reverse the migrations.     *     * @return void     */    public function down()    {        Schema::dropIfExists('admin');    }}

建立Model模型Admin:

php ratisan generate modle Admin

再在生成的文件里添加

<?phpuse Illuminate/Auth/UserTrait;use Illuminate/Auth/UserInterface;use Illuminate/Auth/Reminders/RemindableTrait;use Illuminate/Auth/Reminders/RemindableInterface;class Admin extends /Eloquent implements UserInterface, RemindableInterface {    use UserTrait, RemindableTrait;    protected $fillable = [];    protected $table = 'admin'; // 指定表名    protected $primaryKey = 'id'; // 指定主键名    protected $hidden = array('password');  //密码字段    public $timestamps = false; // 关闭 创建时间 与 更新时间 的自动维护    public function getRememberToken(){        return $this->rememberToken ;    }    public function setRememberToken($value){        $this->rememberToken = $value ;    }    public function getRememberTokenName(){        return $this->reminder ;    }}

解释一下,因为需要做登录验证,用的是laravel自带的Auth所以需要添加use和继承UserInterface以及RemindableInterface接口 并重写一些方法 
具体的就是这几句

use Illuminate/Auth/UserTrait;use Illuminate/Auth/UserInterface;use Illuminate/Auth/Reminders/RemindableTrait;use Illuminate/Auth/Reminders/RemindableInterface;class Admin extends /Eloquent implements UserInterface, RemindableInterface {    use UserTrait, RemindableTrait;    /*******    以下代码省略    *******/    public function getRememberToken(){        return $this->rememberToken ;    }    public function setRememberToken($value){        $this->rememberToken = $value ;    }    public function getRememberTokenName(){        return $this->reminder ;    }    }

然后我继续找到Auth文件的设定 修改一下需要用到的表 
app/config/auth.php 
找到如下字段并修改成自己所指定的表

<?phpreturn array('driver' => 'eloquent', //验证方式,有database和eloquent两种'model' => 'Admin', //所使用的model名'table' => 'admin', //对应的表名'reminder' => array(        'email' => 'emails.auth.reminder',        'table' => 'password_reminders',        'expire' => 60,    ),);

然后再添加controller方法:

    //获取登录页面    public function get_web_login(){        return View::make('web.web_login');    }    //登录验证    public function post_login(){        if (Auth::attempt(array('login_name'=>Input::get('login_name'), 'password'=>Input::get('password')))) {            Notification::success('登录成功');            return Redirect::to('/web/index')            ->with('message', '成功登录');        } else {            Notification::warning('用户名密码不正确');            return Redirect::to('/web/login')            ->with('message', '用户名密码不正确')                ->withInput();        }    }

然后是视图文件login.blade.php:

@section('title')登录 - @parent@stop@section('nav_1')    <li class="active"><a href="#">登录</a></li>@stop@section('selection')    <div id="login" class="login">        <form class="form" role="form" action="{{URL::route('web.web_login.post')}}" style="width: 500px" method="post">            @if (Session::has('message'))                <div class="alert alert-error">{{ Session::get('message')}}</div>            @endif            <div class="form-group">                <label for="login_name">登录名:</label>                <input type="text" class="form-control" id="login_name" name="login_name">                <label for="password">密码:</label>                <input type="password" class="form-control" id="password" name="password">            </div>            <div align="left">                <button type="submit" class="btn btn-info btn-lg"><span class="glyphicon glyphicon-user" aria-hidden="true"></span>&nbsp;&nbsp;登录</button>            </div>        </form>    </div>@stop

最后更新路由

Route::get('/web/index', array('as' => 'web.web_index', 'uses' => 'App/Controllers/Api/WebController@get_web_index'));//登录页面Route::get('/web/login', array('as' => 'web.web_login', 'uses' => 'App/Controllers/Api/WebController@get_web_login'));Route::post('/web/login', array('as' => 'web.web_login.post', 'uses' => 'App/Controllers/Api/WebController@post_login'));

做完以上工作,我就屁颠屁颠的打开数据库 随便塞了条用户数据进去,就尝试登录,然后问题就来了

不管我怎么试,账户密码就是不对

百度google了一下,然而并没有找到什么结果 
无奈之下只能看看laravel的源码 
首先调用的就是attempt方法来验证用户名密码于是我跳转进这个函数去看了下

/**         * Attempt to authenticate a user using the given credentials.         *         * @param array $credentials         * @param bool $remember         * @param bool $login         * @return bool          * @static          */        public static function attempt($credentials = array(), $remember = false, $login = true){            return /Illuminate/Auth/Guard::attempt($credentials, $remember, $login);        }

不难看出她只是返回的Guar::attempt方法的结果,那么我继续进去看

/**     * Attempt to authenticate a user using the given credentials.     *     * @param  array  $credentials     * @param  bool   $remember     * @param  bool   $login     * @return bool     */    public function attempt(array $credentials = array(), $remember = false, $login = true)    {        $this->fireAttemptEvent($credentials, $remember, $login);        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);        // If an implementation of UserInterface was returned, we'll ask the provider        // to validate the user against the given credentials, and if they are in        // fact valid we'll log the users into the application and return true.        if ($this->hasValidCredentials($user, $credentials))        {            if ($login) $this->login($user, $remember);            return true;        }        return false;    }

到了这里,大概就可以知道,登录结果,应该就是那个hasValidCredentials方法返回的结果来控制的,那么它内部是怎样实现的?再进去看看

/**     * Determine if the user matches the credentials.     *     * @param  mixed  $user     * @param  array  $credentials     * @return bool     */    protected function hasValidCredentials($user, $credentials)    {        return ! is_null($user) && $this->provider->validateCredentials($user, $credentials);    }

然而这里只是做了个简单的判断是否存在$user参数,所以我继续转进validateCredentials方法

/**     * Validate a user against the given credentials.     *     * @param  /Illuminate/Auth/UserInterface  $user     * @param  array  $credentials     * @return bool     */    public function validateCredentials(UserInterface $user, array $credentials);

到了这里 初学laravel的我并不能看懂是啥意思,所以只能继续google,然后真的给我找到了一些相关的情报 
扩展Auth功能 
看完这帖子之后,加上上面代码的理解 
顺着它说的目录 
/vender/laravel/framework/src/illuminate/Auth 
于是我找到了EloquentUserProvider.php这个文件 
在其内部找到了validateCredentials方法的具体实现

/**     * Validate a user against the given credentials.     *     * @param  /Illuminate/Auth/UserInterface  $user     * @param  array  $credentials     * @return bool     */    public function validateCredentials(UserInterface $user, array $credentials)    {        $plain = $credentials['password'];        return $this->hasher->check($plain, $user->getAuthPassword());    }

这下就清楚了

laravel在验证密码的时候会把输入的密码用hash运算之后再与数据库所存储的密码对比

然而我是直接在数据库中添加明文密码的,所以显示密码不正确是理所应当的 
所以,在存储密码字段的时候,务必记住用

Hash::make("$passowrd");

来生成对应密码的hash串…… 
然后我在用这个方法向数据库写入密码hash串的时候报错了,检查一看,原来是当初设置的密码字段太短导致的,于是把密码字段长度改为1024个字长 问题就解决了 
这个坑折腾了我一上午……记录下来让大家参考参考,避免再次像我一样被坑吧 
_ (:з」∠)_

另外还找到了一篇bolg,说是怎样将laravel的默认的加密方法换成自定义的MD5加密方式的以后应该会用到吧,贴在这里以供日后参考laravel更改默认的登录密码加密方式

(完)

来自 http://www.th7.cn/Program/php/201507/511215.shtml

普通分类: