Laravel-JWT
JWT简介
JWT(JSON Web Token)实际上是一个字符串,包括头部、载荷、签名
载荷
{
"sub": "1",
"iss": "http://localhost:8000/auth/login",
"iat": 1451888119,
"exp": 1454516119,
"nbf": 1451888119,
"jti": "37c107e4609ddbcc9c096ea5ee76c667"
}
这6个字段是由JWT标准所定义的
- sub:该JWT所面向的对象
- iss:该JWT的签发者
- iat(issued at):在什么时候签发的token
- exp(expires):token什么时候过期
- nbf(not before):token在此时间之前不能被接收处理
- jti:JWT ID为web token提供唯一标识
将上面的JSON对象进行base64编码后得到的字符串就是JWT的载荷
yJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx
ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD
ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
头部
WT还需要一个头部,头部用于描述关于该JWT的最基本的信息
{
//表明其类型和签名算法
"typ": "JWT",
"alg": "HS256"
}
对其进行Base64编码后就得到JWT的头部(Header)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
签名
将头部和荷载编码后的字符串用.
连接在一起(头部在前):
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx
ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD
ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
将上面拼接完的字符串用HS256算法进行加密,同时提供一个密匙(secret):
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
加密后的到的字符串称为签名:
wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4
将这一部分拼接在被签名的字符串后面就形成了JWT
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx
ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD
ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ.wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4
Laravel使用JWT
使用composer安装
composer require tymon/jwt-auth 1.0.0-rc.3
指定版本号,可以根据官网,不指定在生成配置文件时无法生成(坑)
这条命令会在config下增加一个jwt.php配置文件
php artisan vendor:publish –provider=”Tymon\JWTAuth\Providers\LaravelServiceProvider”
生成加密密钥(注意在服务器端拉去代码后要执行这一句话)
php artisan jwt:secret
在config/jwt.php
中可以配置的选项:
- ttl:token有效期(分钟)
- refresh_ttl:刷新token时间(分钟)
- algo:token签名算法
- user:指向User模型的命名空间路径
- identifier:用于从token的sub中获取用户
- require_claims:必须出现在token的payload中的选项,否则会抛出- TokenInvalidException异常
- blacklist_enabled:如果该选项被设置为false,那么我们将不能废止token,即使我们刷新了token,前一个token仍然有效
- providers:完成各种任务的具体实现,如果需要的话你可以重写他们
- User —— providers.user:基于sub获取用户的实现
- JWT —— providers.jwt:加密/解密token
- Authentication —— providers.auth:通过证书/ID获取认证用户
- Storage —— providers.storage:存储token直到它们失效
模型使用
如果使用User表生成token,需要增加一些代码
<?php
namespace App;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject # 这里别忘了加
{
use Notifiable;
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return [];
}
}
>
配置文件修改
注册两个Facade
config/app.php
'aliases' => [
//添加以下两行
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
]
也可以不注册使用这两个Facede,而使用auth()
函数
修改auth.php
config/auth.php
'guards' => [
'web' => [
'driver' => 'session',//改不改视具体情况而定
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // 原来是 token 改成 jwt
'provider' => 'users',
],
],
注册路由
Route::group([
'middleware' => 'api',
'prefix' => 'auth'
],function ($router){
Route::post('login','AuthController@login');
Route::post('logout','AuthController@logout');
Route::post('refresh','AuthController@refresh');
Route::post('me','AuthController@me');
});
创建控制器
php artisan make:controller AuthController
AuthController内容
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;//自定义验证字段时要引入请求
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
public function __construct()
{
$this->middleware('auth:api',['except'=> ['login']]);
}
/**
* Get a JWT via given credentials.
*
* @return \Illuminate\Http\JsonResponse
*/
public function login(Request $request)
{
$credentials = [
'username' => $request->input('username'),
'password' => $request->input('password')
];
//标记用户登录成功
if (! $token = auth('api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
/**
* Get the authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
return response()->json(auth('api')->user());
}
/**
* Log the user out (Invalidate the token).
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
auth()->logout();
return response()->json(['message' => 'Successfully logged out']);
}
/**
* Refresh a token.
*
* @return \Illuminate\Http\JsonResponse
*/
public function refresh()
{
return $this->respondWithToken(auth('api')->refresh());
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}