Laravel 自定义auth认证方法步骤 自定义用户表及字段

关于laravel的认证原理网上有很多介绍,想要了解原理建议通过Xdebug不断调试扒原码来学习,

本文实现了使用自定义用户表,自定义用户表字段名,实现laravel的自定义认证,经过一翻学习和调试,我并没有严格按照网上介绍的原理方法一步一步自定义,而是抄近路直接继承和larave默认的User认证,本文代码中的model、guard和provider均继承自laravel的默认User认证,这样就只需要需要修改自定义内容就可以了,可以不断挖掘laravel默认认证的其它功能,并省去了很多方法重写的麻烦,另外laravel默认的认证方式除了登录认证还有很多其它功能,本文只测试了session和token登录及认证,其它功能没有测试。需要用到其它功能时可以参考默认User使用方法调用,然后再xdebug调试,不能使用默认的部分重写自定义方法就可以了。

github地址:https://github.com/cyberfeipunk/laravelauth

我的自定义认证表名pam_members,步骤如下

1,新建用户认证表Model   App/Models/PamMembers.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User;

/***
继承自laravel默认认证方式的User Model的父类
**/
class PamMembers extends User
{
//
  
  protected $table = 'pam_members';
    var $primaryKey = ['member_id','login_type'];

public $incrementing = false;

/**
* @return mixed|string
* 密码字段
*/
public function getAuthPassword()
{
return $this->login_password; //password字段名
}

/**
* @return string
*/
public function getRememberTokenName(){
return "login_account"; //token字段名称 此处原表没有token字段随便找了个字段测试用
}

/**
* Get the name of the unique identifier for the user.
* 返回用户标识字段
*/
public function getAuthIdentifierName()
{
return "member_id"; //因为这里主键是混合的,所以需要配置一个session记录值字段名
}

}

 

2,新建Session Guard  /App/Http/Auth/SessionGuard.php

<?php

namespace App\Http\Auth;

use Illuminate\Auth\SessionGuard;

/**
 * Class MemberSessionGuard
 * @package App\Http\Auth
 * 继承自laravel默认认证的SessionGurad
 */
class MemberSessionGuard extends SessionGuard
{
    /**
     * Get the currently authenticated user.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function user()
    {
        if ($this->loggedOut) {
            return;
        }

        // If we've already retrieved the user for the current request we can just
        // return it back immediately. We do not want to fetch the user data on
        // every call to this method because that would be tremendously slow.
        if (! is_null($this->user)) {
            return $this->user;
        }

        $id = $this->session->get($this->getName());

        // First we will try to load the user using the identifier in the session if
        // one exists. Otherwise we will check for a "remember me" cookie in this
        // request, and if one exists, attempt to retrieve the user using that.
        if (! is_null($id) && $this->user = $this->provider->retrieveById($id)) {
            $this->fireAuthenticatedEvent($this->user);
        }

        // If the user is null, but we decrypt a "recaller" cookie we can attempt to
        // pull the user data on that cookie which serves as a remember cookie on
        // the application. Once we have a user we can return it to the caller.
        $recaller = $this->recaller();

        if (is_null($this->user) && ! is_null($recaller)) {
            $this->user = $this->userFromRecaller($recaller);

            if ($this->user) {
                $this->updateSession($this->user->getAuthIdentifier());

                $this->fireLoginEvent($this->user, true);
            }
        }

        return $this->user;
    }
}

3,新建Token Guard    /App/Http/Auth/MemberTokenGuard.php

<?php

namespace App\Http\Auth;

use Illuminate\Auth\SessionGuard;
use Illuminate\Auth\TokenGuard;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Http\Request;

/**
 * Class MemberTokenGuard
 * @package App\Http\Auth
 * 继承自laravel默认token认证
 */
class MemberTokenGuard extends TokenGuard
{
    /**
     * Create a new authentication guard.
     *
     * @param  \Illuminate\Contracts\Auth\UserProvider  $provider
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $inputKey
     * @param  string  $storageKey
     * @return void
   * 参数中$inputKey和$storageKey写为token字段名
*/ public function __construct(UserProvider $provider, Request $request, $inputKey = 'login_account', $storageKey = 'login_account') { $this->request = $request; $this->provider = $provider; $this->inputKey = $inputKey; $this->storageKey = $storageKey; } }

4,新建Provider    /App/Http/Auth/EloquentMemberProvider.php

<?php

namespace App\Http\Auth;

use Illuminate\Support\Str;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Auth\EloquentUserProvider;

/**
 * Class EloquentMemberProvider
 * @package App\Http\Auth
 * 继承自laravel默认
 */
class EloquentMemberProvider extends EloquentUserProvider
{
    /**
     * Retrieve a user by the given credentials.
     *
     * @param  array  $credentials
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByCredentials(array $credentials)
    {
        if (empty($credentials) ||
            (count($credentials) === 1 &&
                array_key_exists('login_password', $credentials))) {
            return;
        }

        // First we will add each credential element to the query as a where clause.
        // Then we can execute the query and, if we found a user, return it in a
        // Eloquent User "model" that will be utilized by the Guard instances.
        $query = $this->createModel()->newQuery();

        foreach ($credentials as $key => $value) {
            if (Str::contains($key, 'login_password')) {
                continue;
            }

            if (is_array($value) || $value instanceof Arrayable) {
                $query->whereIn($key, $value);
            } else {
                $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['login_password'];

        //return $this->hasher->check($plain, $user->getAuthPassword());
        return $this->checkMemberPassword($user,$plain);
    }

    //自定义表密码加密方式
    public function createMemberPassword($user,$password){
        $account = $user->password_account;
        $createtime = $user->createtime;
        $string_md5 = md5(md5($password).$account.$createtime);
        $front_string = substr($string_md5,0,31);
        $end_string = 's'.$front_string;
        return $end_string;
    }
    //密码验证
    public function checkMemberPassword($user,$passowrd){
        $enPassword = $this->createMemberPassword($user,$passowrd);
        if($user->login_password === $enPassword){
            return true;
        }else{
            return false;
        }
    }
}

5,服务注册在/app/Providers/AppServiceProvider.php boot方法中加入如下代码

/**
注意增加use列表

use App\Http\Auth\EloquentMemberProvider;
use App\Http\Auth\MemberTokenGuard;
use App\Http\Auth\MemberSessionGuard;
use Auth;*/
        //扩展 membersessionguard 认证方式
        Auth::extend('membersessionguard',function($app, $name, $config){

            $guard_config =$this->app['config']['auth.guards.'.$name];
            $provider_config = $this->app['config']['auth.providers.'.$guard_config['provider']];
            $provider = new EloquentMemberProvider($app['hash'], $provider_config['model']);
            $guard = new MemberSessionGuard($name, $provider, $this->app['session.store']);
            // When using the remember me functionality of the authentication services we
            // will need to be set the encryption instance of the guard, which allows
            // secure, encrypted cookie values to get generated for those cookies.
            if (method_exists($guard, 'setCookieJar')) {
                $guard->setCookieJar($this->app['cookie']);
            }

            if (method_exists($guard, 'setDispatcher')) {
                $guard->setDispatcher($this->app['events']);
            }

            if (method_exists($guard, 'setRequest')) {
                $guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
            }
            return $guard;
        });
        //扩展membersessionguard认证方式
        Auth::extend('membertokenguard', function($app,$name,$config){
            // The token guard implements a basic API token based guard implementation
            // that takes an API token field from the request and matches it to the
            // user in the database or another persistence layer where users are.
            $guard_config =$this->app['config']['auth.guards.'.$name];
            $provider_config = $this->app['config']['auth.providers.'.$guard_config['provider']];
            $provider = new EloquentMemberProvider($app['hash'], $provider_config['model']);
            $guard = new MemberTokenGuard($provider, $this->app['request']);
            $this->app->refresh('request', $guard, 'setRequest');
            return $guard;
        });

        //扩展认证方式的服务提供
        Auth::extend("eloqumentmemberprovider",function(){
            return new EloquentMemberProvider();
        });

 

6,配置/config/auth.php

/**
元素guards下增加如下子元素
*/ 'membersession' =>[ 'driver' => 'membersessionguard', //AppServiceProvider中配置的名子 'provider' => 'members' //providers中的名子 ], 'membertoken' => [ 'driver' => 'membertokenguard', 'provider' => 'members' ] /* 元素providers增加如下子元素说明
*/ 'members' => [ 'driver' => 'eloqumentmemberprovider', //AppServiceProvider中配置的服务名 'model' => App\Models\PamMembers::class, ]

 

7,session登录测试

public function login(){
        $credentials = ['login_account'=>'cyberpunk','login_password'=>'123456'];
        $remember = false;
        $guard = Auth::guard('membersession');
        $loginResult = $guard->attempt($credentials,$remember);
        return $this->responseJson($loginResult);
    }

8,session验证测试

        $guard = Auth::guard('membersession');
        if($guard->check()){
            return "已经登录";
        }else{
           return '未登录';
        }

9,token认证测试

        /*
        * 测试请求header增加参数Authorization参数值为字符串 'Bearer '+token  注意中间有空格
        **/
        $guard = Auth::guard('membertoken');
        if($guard->check()){
           return '认证成功';
        }else{
           return '认证失败';
        }            

 

 

 

 

 

 

 

 

 

 

 

  

 
posted @ 2019-01-28 16:19  cyberpunk_blog  阅读(163)  评论(0)    收藏  举报