一、前言

  1. 如果需要使用 Passport,可以参考在下之前的教程: 'Lumen5.4配置OAuth2.0【强迫症,就是要用最新版本的Lumen】' 。
  2. 由于原作者文档的简洁性,同时 Lumen 下的 JWT 与 Laravel 略有不同,导致新手初学不易理解。
  3. 在下经过多番考究,总结出 Lumen 使用 JWT 的基本过程。同时给出JWT的介绍
  4. 经过少数同学的反馈,教程太过仓促,现重新补充完整。

二、说明

  1. 不知不觉 Lumen 已经更新到 '5.6.x' 版本,因此本文也紧跟脚步,使用最新版的 Lumen 进行讲解,最重要的是 Laravel/Lumen 5.6.x 版本只支持 'PHP7.1' 及以上。
  2. 本文使用 'tymon/jwt-auth: ^1.0.0-rc.2' 版本 (不推荐使用该扩展包的 0.5 版本) 的扩展包,搭配 Laravel 开箱即用的 'Auth' 组件实现  JWT 认证。
  3. 操作环境:'Windows 7' + 'PHP7.2' + 'MariaDB10.3'。上述环境在下均已测试多次,现分享出本人至今 'Windows' 下正常开发使用的整合压缩包

三、准备部分

  1. 检查 'Windows' 上的开发环境是否正常。
    1.1. 查看 'PHP7.2' 环境:

     
    PHP

    1.2. 查看 'MariaDB10.3' 环境:

     
    MariaDB
  2. 安装 'PostMan'以及'Navicat Premium',其他类似软件产品亦可,根据个人喜好就行。
  3. 操作之前查看 'JWT的介绍',对理解后文大有裨益。

四、实现部分

  1. 使用 'Composer' 安装最新的 Lumen 到本地。
  1. composer create-project laravel/lumen jwt-test --prefer-dist
  1. 进入项目 'jwt-test' 中,安装 'tymon/jwt-auth: ^1.0.0-rc.2' 到本地。
  1. composer require tymon/jwt-auth ^1.0.0-rc.2
  1. 刚刚初始化的 Lumen 项目可能会有一个小小的 BUG,因为 Lumen 默认会加载 Memcached 作为缓存,而部分开发者并没有使用 Memcached,所以需要在使用 Lumen项目之前,修改缓存配置。

3.1.首先模拟 Laravel 目录结构,复制'vender/laravel/lumen-framework'下的 'config 目录到 'jwt-test' 根路径。复制完成以后 'jwt-test' 的根目录结构如下:

  1. /app
  2. ......others.......
  3. /config <<<<<< 配置文件目录
  4. /vendor
  5. ......others.......

3.2. 以后的配置文件,都只需要在根路径下的 'config目录操作即可,所以接着修改目录中的 cache.php 文件:

  1. # Dir: /jwt-test/config/cache.php
  2. <?php
  3. return [
  4. #### 修改为文件缓存
  5. 'default' => env('CACHE_DRIVER', 'file'),
  6. #### 同时删除了下面的Memcached配置
  7. 'stores' => [
  8. 'apc' => [
  9. 'driver' => 'apc',
  10. ],
  11. 'array' => [
  12. 'driver' => 'array',
  13. ],
  14. 'database' => [
  15. 'driver' => 'database',
  16. 'table' => env('CACHE_DATABASE_TABLE', 'cache'),
  17. 'connection' => env('CACHE_DATABASE_CONNECTION', 'mysql_a'),
  18. ],
  19. 'file' => [
  20. 'driver' => 'file',
  21. 'path' => storage_path('framework/cache'),
  22. ],
  23. 'redis' => [
  24. 'driver' => 'redis',
  25. 'connection' => env('CACHE_REDIS_CONNECTION', 'cache'),
  26. ]
  27. ],
  28. 'prefix' => env('CACHE_PREFIX', 'wz'),
  29. ];

同时修改根路径下的 '.env 文件:

  1. # Dir: /jwt-test/.env
  2. ......others.......
  3. APP_KEY=9TBF8FrZZgYBoM0AzKjkii/yb6TJVm11 #### Lumen默认没有设置APP_KEY
  4. CACHE_DRIVER=file #### 修改为文件缓存
  5. ......others (包括MySQL的配置项) .......
  6. JWT_SECRET=Bi43uQQTHxLSnUaIOgTEUT1SkGHiOc1o #### JWT编码时需要的Key
  1. 完成上述更改之后,快速启动项目,在 'PostMan' 中访问即可看见输出 Lumen 的版本信息。

     
    On Server

本文使用以下指令快速启动服务。

  1. # Dir: /jwt-test/
  2. php -S localhost:8080 public/index.php
  1. 下面开始实现 JWT 功能。在下习惯在 'app' 路径想新建一个 'Models' 目录存放模型,因此之后的项目目录结构是:
  1. ......others.......
  2. /app
  3. ..........others.......
  4. ..../Models <<<<<< 模型文件目录
  5. /config <<<<<< 配置文件目录
  6. /vendor
  7. ......others.......

5.1 修改 'bootstrap' 文件夹下的 'app.php' 如下所示:

  1. <?php
  2. require_once __DIR__.'/../vendor/autoload.php';
  3. try {
  4. (new Dotenv\Dotenv(__DIR__.'/../'))->load();
  5. } catch (Dotenv\Exception\InvalidPathException $e) {
  6. //
  7. }
  8. $app = new Laravel\Lumen\Application(
  9. realpath(__DIR__.'/../')
  10. );
  11. // 取消注释
  12. $app->withFacades();
  13. $app->withEloquent();
  14. $app->singleton(
  15. Illuminate\Contracts\Debug\ExceptionHandler::class,
  16. App\Exceptions\Handler::class
  17. );
  18. $app->singleton(
  19. Illuminate\Contracts\Console\Kernel::class,
  20. App\Console\Kernel::class
  21. );
  22. // 取消注释
  23. $app->routeMiddleware([
  24. 'auth' => App\Http\Middleware\Authenticate::class,
  25. ]);
  26. // 取消注释
  27. $app->register(App\Providers\AppServiceProvider::class);
  28. $app->register(App\Providers\AuthServiceProvider::class);
  29. $app->register(App\Providers\EventServiceProvider::class);
  30. // 新增JWT的注册
  31. $app->register(Tymon\JWTAuth\Providers\LumenServiceProvider::class);
  32. $app->router->group([
  33. 'namespace' => 'App\Http\Controllers',
  34. ], function ($router) {
  35. require __DIR__.'/../routes/web.php';
  36. });
  37. return $app;

5.2. 修改 'config' 文件夹下的 'auth.php' 如下所示:

  1. <?php
  2. return [
  3. 'defaults' => [
  4. 'guard' => 'api',
  5. 'passwords' => 'users',
  6. ],
  7. 'guards' => [
  8. 'api' => [
  9. 'driver' => 'jwt', #### 更改为JWT驱动
  10. 'provider' => 'users',
  11. ],
  12. ],
  13. 'providers' => [
  14. 'users' => [
  15. 'driver' => 'eloquent',
  16. 'model' => \App\Models\User::class, #### 指定用于token验证的模型类
  17. ],
  18. ],
  19. 'passwords' => [ #### Lumen默认无session,所以该字段无意义
  20. //
  21. ],
  22. ];

5.3. 修改 'app/Providers' 文件夹下的 'AuthServiceProvider.php' 如下所示:

  1. <?php
  2. namespace App\Providers;
  3. use App\Models\User;
  4. use Illuminate\Support\Facades\Gate;
  5. use Illuminate\Support\ServiceProvider;
  6. class AuthServiceProvider extends ServiceProvider
  7. {
  8. /**
  9. * Register any application services.
  10. *
  11. * @return void
  12. */
  13. public function register()
  14. {
  15. //
  16. }
  17. /**
  18. * Boot the authentication services for the application.
  19. *
  20. * @return void
  21. */
  22. public function boot()
  23. {
  24. // 当使用auth中间件的api门卫的时候验证请求体
  25. $this->app['auth']->viaRequest('api', function ($request)
  26. {
  27. return app('auth')->setRequest($request)->user();
  28. });
  29. }
  30. }

5.4. 修改 'app/Models' 文件夹下的 'User.php' 如下所示:

  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Auth\Authenticatable;
  4. use Illuminate\Database\Eloquent\Model;
  5. use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
  6. use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
  7. use Laravel\Lumen\Auth\Authorizable;
  8. use Tymon\JWTAuth\Contracts\JWTSubject;
  9. class User extends Model implements AuthenticatableContract, AuthorizableContract, JWTSubject
  10. {
  11. use Authenticatable, Authorizable;
  12. protected $table = 'users';
  13. /**
  14. * The attributes that are mass assignable.
  15. *
  16. * @var array
  17. */
  18. protected $fillable = [
  19. 'username', 'email',
  20. ];
  21. /**
  22. * The attributes excluded from the model's JSON form.
  23. *
  24. * @var array
  25. */
  26. protected $hidden = [
  27. 'password',
  28. ];
  29. /**
  30. * JWT
  31. *
  32. * @author AdamTyn
  33. */
  34. public function getJWTIdentifier()
  35. {
  36. return $this->getKey();
  37. }
  38. /**
  39. * JWT
  40. *
  41. * @author AdamTyn
  42. */
  43. public function getJWTCustomClaims()
  44. {
  45. return [];
  46. }
  47. }

5.5. 在 'app/Http/Controller' 文件夹下新建 'UserController.php',内容如下所示:

  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Support\Facades\Auth;
  5. use Illuminate\Support\Facades\DB;
  6. class AuthController extends Controller
  7. {
  8. /**
  9. * 登录
  10. *
  11. * @author AdamTyn
  12. *
  13. * @param \Illuminate\Http\Request;
  14. * @return \Illuminate\Http\Response;
  15. */
  16. public function login(Request $request)
  17. {
  18. $response = array('code' => '0');
  19. try {
  20. $user = \App\Models\User::where('username', $request->input('username'))
  21. ->where('password', $request->input('password'))->first();
  22. if (!$token = Auth::login($user)) {
  23. $response['code'] = '5000';
  24. $response['errorMsg'] = '系统错误,无法生成令牌';
  25. } else {
  26. $response['data']['user_id'] = strval($user->id);
  27. $response['data']['access_token'] = $token;
  28. $response['data']['expires_in'] = strval(time() + 86400);
  29. }
  30. } catch (QueryException $queryException) {
  31. $response['code'] = '5002';
  32. $response['msg'] = '无法响应请求,服务端异常';
  33. }
  34. return response()->json($response);
  35. }
  36. /**
  37. * 用户登出
  38. *
  39. * @author AdamTyn
  40. *
  41. * @return \Illuminate\Http\Response;
  42. */
  43. public function logout()
  44. {
  45. $response = array('code' => '0');
  46. Auth::invalidate(true);
  47. return response()->json($response);
  48. }
  49. /**
  50. * 更新用户Token
  51. *
  52. * @author AdamTyn
  53. *
  54. * @param \Illuminate\Http\Request;
  55. * @return \Illuminate\Http\Response;
  56. */
  57. public function refreshToken()
  58. {
  59. $response = array('code' => '0');
  60. if (!$token = Auth::refresh(true, true)) {
  61. $response['code'] = '5000';
  62. $response['errorMsg'] = '系统错误,无法生成令牌';
  63. } else {
  64. $response['data']['access_token'] = $token;
  65. $response['data']['expires_in'] = strval(time() + 86400);
  66. }
  67. return response()->json($response);
  68. }
  69. }

5.6. 最后,我们要利用 'auth' 中间件的 'api' 门卫,修改 'app/Http/Middleware' 文件夹下的 'Authenticate.php',内容如下所示:

  1. <?php
  2. namespace App\Http\Middleware;
  3. use Closure;
  4. use Illuminate\Contracts\Auth\Factory as Auth;
  5. class Authenticate
  6. {
  7. /**
  8. * The authentication guard factory instance.
  9. *
  10. * @var \Illuminate\Contracts\Auth\Factory
  11. */
  12. protected $auth;
  13. /**
  14. * Create a new middleware instance.
  15. *
  16. * @param \Illuminate\Contracts\Auth\Factory $auth
  17. * @return void
  18. */
  19. public function __construct(Auth $auth)
  20. {
  21. $this->auth = $auth;
  22. }
  23. /**
  24. * 在进入控制器之前,判断并处理请求体
  25. *
  26. * @param \Illuminate\Http\Request $request
  27. * @param \Closure $next
  28. * @param string|null $guard
  29. * @return mixed
  30. */
  31. public function handle($request, Closure $next, $guard = null)
  32. {
  33. if ($this->auth->guard($guard)->guest()) {
  34. $response['code'] = '4001';
  35. $response['errorMsg'] = '无效令牌,需要重新获取';
  36. return response()->json($response);
  37. }
  38. return $next($request);
  39. }
  40. }

5.7. 创建 'user' 数据表,在数据库中简单填充一条数据。需要注意的是 Lumen 默认数据库使用 'utf8mb4' 编码,如果数据库版本较低,需要修改'app/Providers/AppServiceProvider.PHP' 如下:

  1. <?php
  2. namespace App\Providers;
  3. use Illuminate\Support\Facades\Schema;
  4. use Illuminate\Support\ServiceProvider;
  5. class AppServiceProvider extends ServiceProvider
  6. {
  7. /**
  8. * Register any application services.
  9. *
  10. * @return void
  11. */
  12. public function register()
  13. {
  14. Schema::defaultStringLength(191);
  15. }
  16. }
 
tb_users
  1. 运行测试。在'routers/router.php' 中添加相应的路由规则。
  1. <?php
  2. $router->post('login','AuthController@login');
  3. $router->group(['prefix'=>'/','middleware'=>'auth:api'],function () use ($router){
  4. $router->post('logout','AuthController@logout');
  5. $router->post('refresh','AuthController@refreshToken');
  6. });

最后,可以得出以下测试结果。

 
login
 
logout
 
refresh

原文地址 https://www.jianshu.com/p/206d0a27a8d1

Lumen5.6使用JWT【最新教程】,亲身失败百次的总结的更多相关文章

  1. JWT 基础教程

    原文地址:JWT 基础教程 博客地址:http://www.extlight.com 一.前言 针对前后端分离的项目,大多是通过 token 进行身份认证来进行交互,今天将介绍一种简单的创建 toke ...

  2. VS2019打包WPF安装程序最新教程

    VS2019打包WPF安装程序最新教程,使用Visual Studio 2019开发的WPF程序如果想要打包为安装程序,除了在VS2019找到WPF项目类库直接右键发布之外,更常用的还是将其打包为ex ...

  3. 使用VS 2019发布.net core程序并部署到IIS的最新教程

    不管你是使用.net core开发的是web api还是网站类的程序,如果你是部署到IIS,那么下面的内容都适合于你,不会将.net core程序部署到IIS的朋友,可以看看这篇手把手教你部署.net ...

  4. React Gatsby 最新教程

    React Gatsby 最新教程 https://www.gatsbyjs.com/docs/quick-start/ https://www.gatsbyjs.com/docs/tutorial/ ...

  5. VuePress 最新教程

    VuePress 最新教程 https://vuepress.vuejs.org/ https://github.com/vuejs/vuepress VuePress plugins 插件通常会为 ...

  6. Storybook 最新教程

    Storybook 最新教程 Storybook is the most popular UI component development tool for React, Vue, and Angul ...

  7. 如何找回微信小程序源码?2020年微信小程序反编译最新教程 小宇子李

    前言:在网上看了找回微信小程序源码很多教程,都没法正常使用.微信版本升级后,会遇到各种报错, 以及无法获取到wxss的问题.查阅各种资料,最终解决,于是贴上完整的微信小程序反编译方案与教程. 本文章仅 ...

  8. 极路由器刷机安装ss插件最新教程

    极路由器系统升级后,旧的插件已不可用,这里是最新极路由器刷机教程,可实现绑定ss代理账号的功能. 获取root权限 安装开发者插件,获取root权限,请先登录极路由器后台(电脑浏览器访问 192.16 ...

  9. SSM框架搭建最新教程(超详细)

    个人认为使用框架并不是很难,关键要理解其思想,这对于我们提高编程水平很有帮助.不过,如果用都不会,谈思想就变成纸上谈兵了!!!先技术,再思想.实践出真知. 1.基本概念 1.1.Spring  Spr ...

随机推荐

  1. Windows下安装RabbitMQ3.6.5

    1.安装erlang 网址:http://www.erlang.org/ 下载exe文件安装即可 2.安装RabbitmQ 下载地址:http://www.rabbitmq.com/download. ...

  2. 转Python 爬虫入门实战

    转自:https://www.cnblogs.com/babycomeon/p/11651888.html

  3. 【serviceaccount 和 clusterrolebinding】

    kubectl get clusterrolebinding kubectl create clusterrolebinding suosheng-rebinding --clusterrole=cl ...

  4. centos配置/etc/mail.rc发邮件

    安装mailx: yum install mailx vi /etc/mail.rc set from=524755798@qq.comset smtp="smtps://smtp.qq.c ...

  5. Python3之内建模块base64

    Base64是一种用64个字符来表示任意二进制数据的方法. 用记事本打开exe.jpg.pdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符,所以,如果要让记事本这样的 ...

  6. Django: ORM查询中使用or查询

    先引入Q,(原名就叫Q) from django.db.models import Q page_user = User.objects.filter(Q(member_code__contains= ...

  7. How George Washington Angered Lawmakers Over Thanksgiving——VOA慢速英语

    听力地址:How George Washington Angered Lawmakers Over Thanksgiving 中英对照:华盛顿总统将感恩节定为全国性节日 Words in This S ...

  8. js原生导出excel和csv

    ​ 严格意义来说并不是真正的excel文件,只是可以用excel打开查看而已,实际上的格式是逗号分隔文件即csv文件. 这里有几个坑要说一下: 不加Unicode的utf8头部标识excel打开文件会 ...

  9. Word 查找替换高级玩法系列之 -- 通配符大全A篇

    1. 通配符大全一览 序号 特殊字符(不使用通配符) 代码(不使用通配符) 特殊字符(使用通配符) 代码(使用通配符) 1 任意单个字符 ^? 任意单个字符 ? 2 任意数字 ^### 任意数字(单个 ...

  10. 2019.10.16&17小结

    话说也蛮久没写小结了,主要这两次考试失分严重,还是总结下吧. 10.16 T1 小奇挖矿2 100/0 [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市 ...