JSON Web Token(JWT)是一个轻量级的认证规范,它允许用户和服务器之间传递安全可靠的信息。
在传统的WEB应用中,服务端成功的返回一个响应于两件事。其一是通过一种存储机制保存会话信息(SESSION)。每一个会话都有它独特的信息,常常是一个长的,随机化的字符串,它被用来让未来的请求检索信息。其次,包含在响应头里面的信息使客户端保存了一个COOKIE。服务器自动的在每个子请求里面加上了会话ID,这使得服务器可以通过检索SESSION中的信息来辨别用户。
API应该被设计成无状态的。这意味着没有登录,注销的方法,也没有SESSION和COOKIE。因此,我们引入JWT。
使用jwt进行认证和授权
认证
客户端向服务器发送用于登录的用户名和密码,服务器将用户名和密码和数据库比对成功后,将一条形如
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
的token返回给客户端,客户端应在本地存储这个token。
这条token被.
分为三个部分:头部(Header),载荷(Payload)和签名(Signature)。其中头部的alg
和typ
两个字段定义了此token所使用的加密算法和token类型;载荷中包含有认证用户的信息;签名则将头部和载荷以及key用base64编码后计算SHA256。
授权
在同一个会话中,当客户端再次向服务器发送请求时,将token附带在请求头的Authorization
字段中。服务器验证此token(是否有效,是否在有效期内等)后,即可对客户端授权。
dingo api
是一个为Laravel和Lumen设计的用于更好地实现RESTful API的第三方库,并且兼容jwt-auth。下面我们使用dingo api和jwt-auth来编写一个登录/登录和认证的API。
安装
我们需要安装jwt-auth和dingo api
在composer.json
中加入如下两行
"require": {
"dingo/api": "1.0.*@dev",
"tymon/jwt-auth": "0.5.*"
}
执行安装
composer install
配置
首先配置jwt-auth
编辑config/app.php
,在providers
中加入
'Tymon\JWTAuth\Providers\JWTAuthServiceProvider'
在aliases
中加入
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth'
发布配置
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
生成key
php artisan jwt:generate
接下来配置dingo api,在providers
中加入
Dingo\Api\Provider\LaravelServiceProvider::class
发布配置
php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
创建路由
# routes/api.php
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', function ($api) {
$api->group(['namespace' => 'App\Api\Controllers', function ($api) {
$api->group(['prefix'=>'auth'], function($api) {
$api->post('register', 'AuthController@postRegister');
$api->post('login', 'AuthController@postLogin');
});
//在需要认证的路由加入api.auth中间件
$api->group(['prefix'=>'test', 'middleware' => 'api.auth'], function($api) {
$api->get('/test', 'TestController@test');
});
});
});
注册/登录
# app/Api/Controllers/AuthController.php
//新用户注册
public function postRegister(Request $request){
$this->validate($request, [
'phone' => 'required|unique:users|max:36',
'password' => 'required|max:64',
]);
$payload = $request->all();
//将新注册用户信息写入数据库
try {
$this->authRepo->registerUser($payload);
}catch(\Exception $e){
return response()->json(['status' => 0, 'message' => $e->getMessage()]);
}
//用已注册的信息登录
return $this->postLogin($request);
}
//登录
public function postLogin(Request $request){
$this->validate($request, [
'phone' => 'required|max:36',
'password' => 'required|max:64',
]);
$credentials = $request->only('phone', 'password');
try {
if (! $token = JWTAuth::attempt($credentials)) {
//用户名或密码不正确则返回错误信息
return response()->json(['error' => 1000004, 'message' => '用户名或密码错误'], 401);
}
} catch (JWTException $e) {
return response()->json(['error' => 1000005, 'message' => '创建token失败'], 401);
}
//如果一切正常则返回token
return response()->json(['error' => 0, 'token' => $token], 200);
}
鉴权
在成功登录后,客户端会收到服务器返回的token。在token有效期内(默认是一个小时),客户端在请求需要鉴权的路由时,只需在HTTP请求头中加入名为Authorization
,值为bearer +token
的字段即可,如果token过期则需要重新登录。
在服务器上,api.auth
中间件会自动进行token的鉴定。在Controller中,调用Auth::User()
即可获得已认证的用户实例。
# app/Api/Controllers/TestController.php
public function test(){
$user = Auth::User();
}
发表回复/Leave a Reply