laravel api配置使用jwt(json web token)
1、JWT定义及其组成
JWT(JSON Web Token)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。
一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
载荷(Payload)
我们先将用户认证的操作描述成一个JSON对象。其中添加了一些其他的信息,帮助今后收到这个JWT的服务器理解这个JWT。
{ "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编码可以得到下面的字符串:
eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
这个字符串我们将它称作JWT的Payload(载荷)。
如果你使用Node.js,可以用Node.js的包base64url来得到这个字符串:
var base64url = require('base64url') var header = { "from_user": "B", "target_user": "A" } console.log(base64url(JSON.stringify(header)))
注:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。
头部(Header)
JWT还需要一个头部,头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象:
{ "typ": "JWT", "alg": "HS256" }
在这里,我们说明了这是一个JWT,并且我们所用的签名算法(后面会提到)是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的一些解释
----------------------------------------------------------------------分割线-----------------------------------------------------------------------
因为:php(laravel5.3+)+vue
项目中的代码使用的jwt来提供接口 于是自己也下载了白板框架来搭建jwt
先说说遇到的坑:
最开始我在composer中配置的jwt版本是0.5版本的 获取token以及验证都没有问题 但是在需要用到guard的时候报出了
Auth guard driver [api] is not defined.
我一直以为是自己配置的问题 网上百度了一大堆都不得其解(吐槽一下百度 千篇一律) 最后在Stack Overflow(https://stackoverflow.com/questions/42680573/laravel-5-4-tymon-jwt-auth-guard-driver-not-defined)的一篇文章中貌似找到了答案
最后在jwt的github地址中确定了这一点(https://github.com/tymondesigns/jwt-auth/issues/860)
欲哭无泪!
接下来使用的jwt的develop版本 1.0版本的应该也是差不多的
1.composer.json 中添加 "tymon/jwt-auth": "dev-develop" 并执行update
2.config/app.php 中的provider添加Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
3.aliases里加上 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class
4.发布配置 php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
5.生成jwt-secret php artisan jwt:secret
6.接下来修改config/auth.php、创建User的model与controller
auth.php <?php return [ /* |-------------------------------------------------------------------------- | Authentication Defaults |-------------------------------------------------------------------------- | | This option controls the default authentication "guard" and password | reset options for your application. You may change these defaults | as required, but they're a perfect start for most applications. | */ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], /* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you | here which uses session storage and the Eloquent user provider. | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | Supported: "session", "token" | */ 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ], /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* |-------------------------------------------------------------------------- | Resetting Passwords |-------------------------------------------------------------------------- | | You may specify multiple password reset configurations if you have more | than one user table or model in the application and you want to have | separate password reset settings based on the specific user types. | | The expire time is the number of minutes that the reset token should be | considered valid. This security feature keeps tokens short-lived so | they have less time to be guessed. You may change this as needed. | */ 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ], ];
user model 实现JWTSubject, Authenticatable的方法 <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Contracts\Auth\Authenticatable; use Tymon\JWTAuth\Contracts\JWTSubject; class User extends Model implements JWTSubject, Authenticatable { protected $table = 'users'; /** * Get the identifier that will be stored in the subject claim of the JWT. * * @return mixed */ 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 []; } /** * 主键 * Get the name of the unique identifier for the user. * @return string */ public function getAuthIdentifierName() { return 'id'; } /** * Get the unique identifier for the user. * * @return mixed */ public function getAuthIdentifier() { } /** * Get the password for the user. * * @return string */ public function getAuthPassword() { } /** * Get the token value for the "remember me" session. * * @return string */ public function getRememberToken() { } /** * Set the token value for the "remember me" session. * * @param string $value * @return void */ public function setRememberToken($value) { } /** * Get the column name for the "remember me" token. * * @return string */ public function getRememberTokenName() { } public static function getUserByEmailAndPassword($email = '') { return self::query()->find(1); } }
配置user controller并注入jwtAuth <?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\Request; use Mockery\Exception; use Tymon\JWTAuth\JWTAuth; class UsersController extends Controller { protected $auth; public function __construct(JWTAuth $auth) { $this->auth = $auth; } public function getToken(Request $request) { $user = User::getUserByEmailAndPassword(); $token = $this->auth->fromUser($user); return ApiResponse($token); } public function getUser(Request $request) { if (!$this->auth->parser()->setRequest($request)->hasToken()) throw new Exception('未授权的操作'); try { $token = $this->auth->getToken()->get(); if (!$user = $this->auth->parseToken()->authenticate()) { throw new Exception('身份凭证无效'); } return ApiResponse(['user' => $user, 'token' => $token]); } catch (\Exception $e) { throw new Exception($e->getMessage()); } } /** * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function refreshToken(Request $request) { if (!$this->auth->parser()->setRequest($request)->hasToken()) throw new Exception('未授权的操作'); $token = $this->auth->refresh($this->auth->getToken()); return ApiResponse(['token' => $token]); } }
以上就是全部代码
下面依次是获取token 、登录、以及刷新token的返回截图