laravel jwt用户令牌认证(不使用默认的password字段完成验证)

第一步:安装jwt composer扩展包
composer require tymon/jwt-auth 1.*@rc

第二步:配置jwt的参数
//进入项目根目录执行这条命令,然后会在config文件夹下面生成jwt.php,该文件主要是配置jwt的一些参数,根据你的实际情况去配置即可。

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

//紧接着执行这行命令,会在 .env 文件下生成一个加密密钥,即JWT_SECRET。

php artisan jwt:secret

//我们需要修改下config文件夹下的auth.php文件配置

//这里我们采用api
'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'jwt', //这里默认是token,需要改为jwt
            'provider' => 'users',
        ],
    ],

第三步:使用jwt
//我们这里先创建一个User模型,在模型文件中需要定义两个方法来实现jwt的运行,代码如下:



namespace App\Http\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject; //注意:不要忘记引用这个类

class User extends Authenticatable implements JWTSubject //注意:不要忘记加上这一行
{
    use Notifiable;

    protected $table = 'users';

    protected $primaryKey = 'id';

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
 }

//然后我们需要自定义一个User控制器,来编写如何生成jwt-token以及注销jwt-token

//我们自定义个用户注册方法,需要手机号和验证码作为参数来完成登录
public function Register()
{
	$Phone = $this->request['phone'];
    $Code  = $this->request['code'];

    if(!$PhoneRedisCode = Redis::get('SendSmsCode_'.$Phone)){
      	return response()->json(['code' => 100, 'message' => '请先发送短信验证码!']);
    }

    if($Code !== $PhoneRedisCode){
       return response()->json(['code' => 101, 'message' => '验证码错误或已过期!']);
    }
    
	//根据手机号码获取当前用户id
    $userId = (new User())->getUserIdWithPhone($Phone);
    //获取redis中用户的jwt-token
    $CacheToken = Redis::get('UserToken_'.$userId);
    
    //如果当前用户redis中存在jwt-token的情况下
   	if(!empty($CacheToken)){
        try {
        	//验证redis中的jwt-token是否有效
            $check = auth('api')->setToken($CacheToken)->check();
            if($check){
  	            //如果有效的话将其作废掉,主要应用于用户重复登录的场景,顶下线机制
                auth('api')->setToken($CacheToken)->invalidate();
            }
        } catch (\Exception $exception) {
            Log::error('The func UserEntry invalidate token error is: '.$exception->getMessage());
            return response()->json(['code' => 500, 'message' => '登录失败,请稍后再试!']);
        }
    }
    
    //生成jwt-token,我这里采用用户id和手机号作为加密的参数。
    //ps:attempt方法会自动验证user表中两个字段作为where条件的记录,如果查不到数据或字段错误,这里会返回false。
    //我会在注意事项中说明一下关于自动验证表字段的问题
    if(!$token = auth('api')->attempt(['id' => $userId, 'phone' => $Phone])){
        return response()->json(['code' => 103, 'message' => '用户信息异常,请稍后尝试!']);
    }
    
    //将用户最新的jwt_token存入redis
    Redis::set('UserToken_'.$userId,$token);
    return response()->json(['code' => 200 ,'token' => 'bearer '.$token]);
}

第四步:附加使用说明以及注意事项
1.关于laravel auth自动验证表字段的问题:
有的朋友可能按照我上面的代码步骤去做了,可能会报未定义索引’password’,这是因为我们在生成jwt-token的时候没有将password包含进去,所以才会报错。
解决方法:
修改\vendor\laravel\framework\src\Illuminate\Auth\EloquentUserProvider.php中的validateCredentials方法

	//这个方法就会去自动验证user表中密码是否正常
    public function validateCredentials(UserContract $user, array $credentials)
    {
        return true;  //我这里直接返回true,不去验证即可。
        $plain = $credentials['password'];

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

这种方式目前不知道是不是最佳的方式,如有好的方式请多多指教!

2.jwt的使用技巧:
参考:https://learnku.com/articles/10885/full-use-of-jwt

你可能感兴趣的:(laravel)