第一步:安装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