​laravel api配置使用jwt(json web token)

作者:Shine 发布于:2018-03-11 20:58:05 浏览:1501次 分类:PHP

​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)的一篇文章中貌似找到了答案

image.png

最后在jwt的github地址中确定了这一点(https://github.com/tymondesigns/jwt-auth/issues/860

image.png

欲哭无泪!


接下来使用的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的返回截图

image.png

image.png

image.png

标签: laravel jwt
声明:文章内容由作者原创或整理,转载请标明出处!
暂留位置!--请勿随意修改