乐趣区

关于laravel:Laravel-配合-jwt-使用

测试应用的是 Laravel5.5 版本。

装置

composer require tymon/jwt-auth=1.0.0-rc.5

配置

生成配置

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

php artisan jwt:secret

auth 配置

<?php

return [
    ...

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],


    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        // 应用 jwt
        'api' => [
            'driver' => 'jwt',
            'provider' => 'apiUser',
        ],
    ],


    'providers' => [
        ...
        // 指定 model
        'apiUser' => [
            'driver' => 'eloquent',
            'model' => App\ApiUser::class,
        ],    
    ],
];

编码

控制器:

<?php

namespace App\Http\Controllers\Api;

use App\ApiUser;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Facades\JWTAuth;

class AuthController extends Controller
{
    /**
     * 中间件去除 login 和 refresh
     *
     * @return void
     */
    public function __construct()
    {$this->middleware('auth:api', ['except' => ['login','refresh']]);
    }

    /**
     * Get a JWT via given credentials.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {$credentials = $request->only('phone', 'password');

        if (count($credentials) < 2) {return response()->json(['error' => 'Unauthorized'], 401);
        } 

        $user = ApiUser::where('phone', $credentials['phone'])
            ->where('password', md5($credentials['password']))
            ->first();
        if (empty($user) || !$token = JWTAuth::fromUser($user)) {return response()->json(['error' => 'Unauthorized'], 401);
        }
        // dd($token);

        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
        ]);
    }
}

路由:

此处留神,我为了不便测试,应用了 get 办法,生产环境不倡议应用 get。

// routes/api.php

Route::middleware('api')->prefix('auth')->namespace('Api')->group(function () {Route::get('login', 'AuthController@login');
    Route::post('logout', 'AuthController@logout');
    Route::get('refresh', 'AuthController@refresh');
    Route::get('me', 'AuthController@me');
});

测试一下:



unauthenticated 解决

这里须要留神下,unauthenticated 解决一下比拟好,否则会默认跳转 login 登录页面。

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Auth\AuthenticationException;

class Handler extends ExceptionHandler
{
    ...

    protected function unauthenticated($request, AuthenticationException $exception)
    {return response()->json(['message' => 'Unauthenticated.'], 401);
         /* 非 api 能够这么解决
        return $request->expectsJson()
                    ? response()->json(['message' => 'Unauthenticated.'], 401)
                    : redirect()->guest(route('login'));
                    */
    }
}

退出 token refresh

退出中间件代码:

<?php
namespace App\Http\Middleware;
  
use Closure;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Illuminate\Auth\AuthenticationException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

class RefreshToken extends BaseMiddleware
{

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {  
        try{
            // 查看申请中是否带有 token 如果没有 token 值则抛出异样
            $this->checkForToken($request); 
            if ($request->user = JWTAuth::parseToken()->authenticate()) {return $next($request);
            }
            throw new AuthenticationException('Unauthorized', []);
        }catch (TokenExpiredException $exception){
            // 返回非凡的 code
            throw new HttpResponseException(response()->json(['message' => 'token expired']));
        } catch (\Exception $exception) {throw new AuthenticationException('Unauthorized', []);
        }
    }
}

注册:

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    ...
    protected $routeMiddleware = [
        'token.refresh' => \App\Http\Middleware\RefreshToken::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];
}

相应的控制器构造函数批改:

public function __construct()
{$this->middleware('token.refresh', ['except' => ['login','refresh']]);
}

把 token 工夫设置成 1 分钟,测试一下。

能够依据 api 返回,去调用刷新接口。

简略应用就是这样啦。更多应用能够看下站内其余文章:
JWT 残缺应用详解
jwt-auth 文档

退出移动版