博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Laravel5】Auth组件重写密码认证方式为MD5加密
阅读量:6242 次
发布时间:2019-06-22

本文共 7497 字,大约阅读时间需要 24 分钟。

hot3.png

学习不久Laravel,碰壁非常多,整理一些 Auth组件上的理解,并重写Auth组件密码认证方式为MD5加密的一些调试过程,分享给其他初学Laravel的用户。

需求说明

由于项目是一个老项目,需要将部分数据直接迁移到新项目中直接使用,包括数据库的一些设计需要继续沿用。所以能改动的只有代码逻辑部分。

用户表:uc_user

加密方式 : md5

密码字段:user_pass

 

 

Auth::attempt 校验并登录

Auth::once 校验不登录,用于一次性授权,类似与api接口的场景

Auth::logout 注销登录的用户

Auth::user 获取已经登录的用户信息

Auth::check 检查用户是否已经登录

以上函数来源于哪里?laravel文档、查阅laravel代码打debug得知。

文件位于:/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php

调试是一件很痛苦的事情,以下是调试完毕整理的过程说明,分享给各位需要用到的朋友。

 

1.配置数据库账户密码信息

修改根目录下 .env 文件即可,如图,只修改数据库信息即可,其他可默认。

APP_ENV=localAPP_DEBUG=trueAPP_KEY=base64:IxkVvrRLqdJeU9h8vGu1W58OG3NVuDtkMWyC6nIT4qs=APP_URL=http://www.example.comDB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=ucenter_exampleDB_USERNAME=rootDB_PASSWORD=rootCACHE_DRIVER=fileSESSION_DRIVER=fileQUEUE_DRIVER=syncREDIS_HOST=127.0.0.1REDIS_PASSWORD=nullREDIS_PORT=6379MAIL_DRIVER=smtpMAIL_HOST=mailtrap.ioMAIL_PORT=2525MAIL_USERNAME=nullMAIL_PASSWORD=nullMAIL_ENCRYPTION=null

 

2.创建用户控制器,编写测试登录代码。

artisan:

php artisan make:controller UserController

同样也可以手工进行创建文件:/app/Http/Controllers/UserController.php

文件内容如下:

get('username'); $password = request()->get('password'); //验证账号密码,postdata数据key为数据库存储字段名。 $postdata = ['user_name' => $username, 'user_pass'=>$password]; $ret = Auth::attempt($postdata); if($ret){ return 'success'; } return $username.$password; }}

 

3.增加路由映射

/app/Http/routes.php

 

4.测试进行访问

url:http://www.example.com/login?username=ellermister&password=admin888

021630_uZRW_2366984.png

很明显当前Auth验证生成的SQL语句和我们预想的不太一样。

1. user_pass 不能作为明文查询条件。

2.所查询的表名不是我们的表名。

为此我们进行调试修改。

第一个问题,我们一般通过配置文件就可以解决掉。

查看:/config/auth.php

[ 'guard' => 'web', 'passwords' => 'users', ], /* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | */ 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* |-------------------------------------------------------------------------- | Resetting Passwords |-------------------------------------------------------------------------- */ 'passwords' => [ 'users' => [ 'provider' => 'users', 'email' => 'auth.emails.password', 'table' => 'password_resets', 'expire' => 60, ], ],];

 

通过以上信息,结合路由配置(/app/Http/Kernel.php、/app/Http/routes.php),可以看到我们默认使用的web引擎,其配置的provider是users。

在users provider配置段可以看到当前配置的驱动是 eloquent (对象方式)。

加载的模型是:App\User::class  此刻我们修改这个模型文件。

/app/User.php

 

之后,我们解决过滤user_pass这个字段不被作为查询条件。

通过查询函数: function\s+attempt

得到验证函数位于:/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php

023536_0WBb_2366984.png

图中我们可以看到 $credentials 就是我们传出的 $postdata 用户信息。

重点是画红线的那句,通过我们提供的$postdata来取回用户信息,之后再进行校验口令是否正确。

dd($this->provider);exit;

通过调试这个provider,得到对象文件位置。

023929_F9F9_2366984.png

023950_SV3F_2366984.png

打开同级目录下文件:/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php

定位到 retrieveByCredentials 方法

024140_RoCO_2366984.png

将其原字段名:password 修改为 user_pass。

再次请求调试:url:http://www.example.com/login?username=ellermister&password=admin888

024433_af2X_2366984.png

我们发现基本sql语句正常,表也变成了user,可实际我们的表均有统一的前缀uc_,在此进行修改下配置:

/config/database.php

024603_XzIn_2366984.png

再次请求调试:url:http://www.example.com/login?username=ellermister&password=admin888

024703_IK5j_2366984.png

又是一个错误:未定义 password

我们追踪到这个文件中,116行进行查看。

024831_n3SJ_2366984.png

经过测试,发现$credentials是我们提供数据,密码默认字段是user_pass而不是password,致使导致这个错误。改掉它为 user_pass。

再次请求调试:url:http://www.example.com/login?username=ellermister&password=admin888

025057_AUw8_2366984.png

此次依然没有输出我们预设的success,再次调试文件:

/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php

得到是因为密码校验问题,验证调用依然是在文件:

/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php

方法:validateCredentials

025255_Fjsd_2366984.png

测试发现两个问题:

$user->getAuthPassword()  方法字段取错,无法获取到密码密文;

$this->hasher->check()  验证方式和我们已有的数据密文加密方式不一致,无法正确校验。

继续追踪到这个方法所在的文件:

/vendor/laravel/framework/src/Illuminate/Auth/Authenticatable.php

030529_9ykN_2366984.png

将其进行修改为 user_pass。

另外修改外部验证密码方式为:

/**     * Validate a user against the given credentials.     *     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user     * @param  array  $credentials     * @return bool     */    public function validateCredentials(UserContract $user, array $credentials)    {        $plain = $credentials['user_pass'];		return md5($plain)===$user->getAuthPassword()?true:false;        return $this->hasher->check($plain, $user->getAuthPassword());    }

 

再次请求调试:url:http://www.example.com/login?username=ellermister&password=admin888

030557_CUQS_2366984.png

此时我们终于登录成功。

以上逻辑代码只建议作为调试使用,因为刚才我们都是直接修改框架源代码,可能会带来无法预期的问题,非常不建议这么做,那么实际项目中应用请参见后面改法。

5.常规项目正确修改

整理一下,我们刚才修改过的核心文件。

/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php 修改验证密码字段以及验证方式

/vendor/laravel/framework/src/Illuminate/Auth/Authenticatable.php 修改数据库取回记录的字段

其他文件可以忽略,如有调试代码,可以删除掉,实际修改的文件只有以上两个核心文件(位于:/vendor目录)。

 

laravel一般情况下所有组件都可以进行扩展修改,可以不修改源文件的情况下对其功能进行重写扩展等。

我们接下来进行扩展Auth组件,修改为我们的需求。

 

6.新建 UserProvider

复制 /vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php

到 /app/Foundation/Auth/EllerEloquentUserProvider.php

并修改文件名以及类名(注意,此时文件的位置以及命名完全可以自定义,不要限定于此)

createModel()->newQuery(); foreach ($credentials as $key => $value) { if (! Str::contains($key, 'user_pass')) { $query->where($key, $value); } } return $query->first(); } /** * Validate a user against the given credentials. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(UserContract $user, array $credentials) { $plain = $credentials['user_pass']; return md5($plain)===$user->getAuthPassword()?true:false; return $this->hasher->check($plain, $user->getAuthPassword()); } /* 当前省略 请复制原文件内容即可 */}

 

注入这个UserProvider

/app/Providers/AuthServiceProvider.php

'App\Policies\ModelPolicy', ]; /** * Register any application authentication / authorization services. * * @param \Illuminate\Contracts\Auth\Access\Gate $gate * @return void */ public function boot(GateContract $gate) { $this->registerPolicies($gate); //进行拦截注入,Eller-eloquent 自定义需要与配置文件对应。 Auth::provider('Eller-eloquent', function ($app, $config) { return new EllerEloquentUserProvider($this->app['hash'], $config['model']); }); }}

 

修改配置

/config/auth.php(以下节选)

'providers' => [        'users' => [            'driver' => 'Eller-eloquent',#修改此处,需与上文注入UserProvider对应。            'model' => App\User::class,        ],        // 'users' => [        //     'driver' => 'database',        //     'table' => 'users',        // ],    ],

 

7.重写 getAuthPassword 方法

将Authenticatable.php的getAuthPassword 方法恢复,在User模型里进行重写。

/app/User.php

user_pass; }}

 

8.恢复所有修改核心文件,测试通过。

url:http://www.example.com/login?username=ellermister&password=admin888

033750_it6K_2366984.png

终于测试通过。

需要注意的是:

测试登录就要单纯的测试登录,不管其他的,只测试是否能登陆成功,再去看其他的。否则有可能出现我之前的惨状,各种问题缠绕在一起,很难分辨,到最后很难坚持下去。

比如:laravel的落地Session机制、laravel的Csrf安全机制、密码加密方法。

转载于:https://my.oschina.net/u/2366984/blog/895431

你可能感兴趣的文章
如何有效释放DB2所占的磁盘空间?
查看>>
三分法
查看>>
第 8 章 容器网络 - 058 - flannel 概述
查看>>
Mongodb删除collection
查看>>
ArcEngine应用程序中无法实现TOC图层多选
查看>>
Java-笔记9-复习
查看>>
python---基本数据结构
查看>>
Windows下JDK,Tomcat,Eclipse安装配置
查看>>
vue的checkbox或多选的select的代码例子
查看>>
es6-Set和Map数据结构
查看>>
使用ffmpeg将录屏文件转换成gif
查看>>
作业七 总结
查看>>
Oracle的静默安装 升级和卸载 参考规范
查看>>
高效存储过程分页
查看>>
电脑用U盘启动
查看>>
Web漏洞扫描
查看>>
使用xtrabackup做数据库的增量备份
查看>>
“程序已停止工作”问题的解决方法,停止解决方法
查看>>
[c++] 幂法求特征向量
查看>>
WEB项目(B/S系统)打包安装(总结篇)
查看>>