一、配置
config/auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',//指向llluminate/Auth/SessionGuard.php
'provider' => 'users',
],
'api' => [
'driver' => 'token', //指向llluminate/Auth/TokenGuard.php
'provider' => 'wx_user',
'hash' => false,//TokenGuard.php文件类属性
'input' => 'token', //TokenGuard.php文件类属性
'storage_key' => 'token', //TokenGuard.php文件类属性
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'wx_user' => [
'driver' => 'eloquent',
'model' =>App\Model\UserModel::class,
]
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
二、基础使用
Auth::check() //判断用户是否登陆,false则重定向/login,为什么用Redirect::guest()而不用Redirect::to()?因为guest() 重定向时会将当前url保存到session中,登陆后用Redirect::intended()方法跳转之前页面。
Auth::attempt(array('email' => $email, 'password' => $password)) //attempt 接收数组作为参数1,该参的值将用于寻找数据库中的用户数据。如用 email 值在数据库中查找,如找到则将 password 值哈希加密并与数据库中密码匹配,如果匹配到,则创建认证通过的会话给用户。当用户身份认证成功 attempt 方法会返回 true,反之则返回 false。
//Auth只帮助实现验证逻辑,如果成功会写入session,下次Auth::check()的时就通过了。
//Redirect::intended(‘/’)跳转到之前页面,如Redirect::guest()方法,那intended会跳转到那时的url,而它的参数只是个默认值,再没有记录历史url的时候会跳转到’/’。
//Auth还有些其他方法,如 Auth::basic() 可实现http basic认证。
三、自定义加密验证
3.1 寻找auth模块
# config/app.php
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
调用Auth其实是调用 Illuminate\Support\Facades\Auth::class
,打开文件
class Auth extends Facade{
protected static function getFacadeAccessor(){
return 'auth';
}
}
Auth是通过Facade动态绑定的,绑定到 vendor/laravel/framework/src/Illuminate/AuthServiceProvider
中
class AuthServiceProvider extends ServiceProvider{
protected function registerAuthenticator(){
$this->app->singleton('auth', function ($app) {
$app['auth.loaded'] = true;
return new AuthManager($app);
});
$this->app->singleton('auth.driver', function ($app) {
return $app['auth']->guard();
});
}
}
默认Auth
绑定了AuthManager
,打开AuthManager
文件
<?php
namespace Illuminate\Auth;
use Closure;
use InvalidArgumentException;
use Illuminate\Contracts\Auth\Factory as FactoryContract;
class AuthManager implements FactoryContract{
use CreatesUserProviders;
protected $app;
protected $guards = [];
public function guard($name = null){
$name = $name ?: $this->getDefaultDriver();
return $this->guards[$name]??$this->guards[$name] = $this->resolve($name);
}
public function getDefaultDriver(){
return $this->app['config']['auth.defaults.guard'];
}
public function __call($method, $parameters){
return $this->guard()->{$method}(...$parameters);
}
}
没找到attempt方法,但有__call
魔术方法,直接用 dd(get_class($this->guard()));
真正的attempt被谁调用呢?打印SessionGuard,打开Illuminate\Auth\SessionGuard,终于发现attempt实现
class SessionGuard implements StatefulGuard, SupportsBasicAuth
{
use GuardHelpers, Macroable;
public function attempt(array $credentials = [], $remember = false){
$this->fireAttemptEvent($credentials, $remember);
$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
if ($this->hasValidCredentials($user, $credentials)) {
$this->login($user, $remember);
return true;
}
$this->fireFailedEvent($user, $credentials);
return false;
}
这是attempt
实现,通过 $this->provider->retrieveByCredentials($credentials)
获取用户信息,并验证,如果成功则登录,并返回true,所以我们真正做的密码验证肯定在retrieveByCredentials
这个方法里面 Laravel 默认提供了 UserProvider
为 EloquentUserProvider
打开改方法
class EloquentUserProvider implements UserProvider{
protected $hasher;
protected $model;
public function __construct(HasherContract $hasher, $model){
$this->model = $model;
$this->hasher = $hasher;
}
public function validateCredentials(UserContract $user, array $credentials){
$plain = $credentials['password'];
return $this->hasher->check($plain, $user->getAuthPassword());
}
public function setHasher(HasherContract $hasher){
$this->hasher = $hasher;
return $this;
}
}
所以这里的hasher就是系统默认的BcryptHasher了,修改他并注入自己的haser。ok,开始搞它
3.2 编写自己的密码规则hasher
<?php
namespace App\Helpers\Hasher;
use Illuminate\Contracts\Hashing\Hasher;
class MD5Hasher implements Hasher{
public function check($value, $hashedValue, array $options = []){
return $this->make($value) === $hashedValue;
}
public function needsRehash($hashedValue, array $options = []){
return false;
}
public function make($value, array $options = []){
$value = env('SALT', '').$value;
return md5($value); //这里写你自定义的加密方法
}
}
3.3 用自己的Hasher替换默认的Hasher
创建MD5HashServiceProvider
php artisan make:provider MD5HashServiceProvider
添加如下方法
<?php
namespace App\Providers;
use App\Helpers\Hasher\MD5Hasher;
use Illuminate\Support\ServiceProvider;
class MD5HashServiceProvider extends ServiceProvider{
public function boot(){
$this->app->singleton('hash', function () {
return new MD5Hasher;
});
}
public function register(){}
public function provides(){
return ['hash'];
}
}
然后在config/app.php
的providers
中,将 Illuminate\Hashing\HashServiceProvider::class,
替换为 \App\Providers\MD5HashServiceProvider::class,
OK,大功告成
四、自定义auth 验证
4.1 修改 user model
# 新增,获取需验证的字段
public function getAuthPassword (){
return [
'password'=> $this->attributes['password'],
'salt'=> $this->attributes['code']
];
}
4.2 新增 provider
php artisan make:provider UserServiceProvider
# 重写EloquentUserProvider类的validateCredentials方法
class MyUserProvider extends EloquentUserProvider{
public function __construct (HasherContract $hasher, $model){
$this->model = $model;
$this->hasher = $hasher;
}
public function register(){}
public function boot(){}
// 认证给定的用户和给定的凭证是否符合
public function validateCredentials (Authenticatable $user, array $credentials){
$plain = $credentials['password'];
$secret = $user->getAuthPassword();
if(password_verify($plain, $secret)){
return true;
} elseif($this->think_ucenter_md5($plain) === $secret){
$user->password = password_hash($plain, PASSWORD_DEFAULT);
$user->save();
return true;
}
}
public function think_ucenter_md5 ($str){
return md5(sha1($str) . 'VvKl0QZBE7nao5xtXqGkWrMPchRbHdwmLF361izT');
}
}
4.3 在 AppServiceProvider 的 boot 注册
Auth::provider('myuserprovider', function(){
return new MyUserProvider(); // 返回自定义的 user provider
});
4.4 修改 config/auth.php
在 config\auth.php
的 guards 数组中添加自定义 guard,一个自定义 guard 包括两部分: driver 和 provider.
'oustn' => [
'driver' => 'myguard',
'provider' => 'myusers',
],
...
//在providers 数组中添加自定义 user provider
'myusers' => [
'driver' => 'myuserprovider' //具体字段根据创建 user provider 的信息添加,通过 Auth::createUserProvider('myuserprovider')创建
],
五、auth常用函数
<?php
Auth::guard("api")->user();// 获取当前认证的用户
Auth::guard("api")->check();// 判断当前用户是否登录
Auth::guard("api")->guest();// 判断当前用户是否是游客(未登录)
Auth::guard("api")->validate();// 根据提供的消息认证用户
Auth::guard("api")->setUser();// 设置当前用户
Auth::guard("api")->attempt();// 根据提供的凭证验证用户是否合法
Auth::guard("api")->id();