使用 Lumen(v5.8) 构建 JWT 认证 API

2025-06-07

使用 Lumen(v5.8) 构建 JWT 认证 API

在本教程中,我们将使用 Lumen(Laravel 开发的一款超快速微框架)来构建一个简单安全的 REST API。完成本教程后,您将能够构建可用于生产的 API。让我们开始吧!

先决条件

我恳求你,确保你拥有必需品。

  • PHP >= 7.1.3
  • OpenSSL PHP 扩展
  • PDO PHP 扩展
  • Mbstring PHP 扩展
  • Mysql >= 5.7
  • Composer(PHP 依赖管理器)
  • Postman(用于测试您的端点)

安装

首先,您需要获取 lumen 的 cli。

$ composer global require "laravel/lumen-installer"
Enter fullscreen mode Exit fullscreen mode

如果下载成功,请运行以下命令来确认您已安装流明。

$ lumen
Enter fullscreen mode Exit fullscreen mode

如果遇到类似的错误-bash: lumen: command not found,则需要将作曲家的供应商 bin 添加到您的路径中

如果一切正常,您应该会看到类似这样的内容。

流明

现在运行此命令来创建 lumen 项目

$ lumen new auth-app
Enter fullscreen mode Exit fullscreen mode

进入项目文件夹

$ cd auth-app
Enter fullscreen mode Exit fullscreen mode

运行应用

$ php -S localhost:8000 -t public
Enter fullscreen mode Exit fullscreen mode

在您的浏览器地址栏上加载localhost:8000,它将呈现如下所示的结果。

流明响应

在您喜欢的编辑器中打开项目(auth-app)。

创建一个 .env 文件,将 .env.example 中的所有内容复制到 .env 文件中并添加数据库配置。

取消boostrap/app.php注释外观和雄辩的方法

//before

// $app->withFacades();

// $app->withEloquent();

//after

$app->withFacades();

$app->withEloquent();

Enter fullscreen mode Exit fullscreen mode

启用 withFacades 会将应用程序的 IoC 注入到 Illuminate\Support\Facades\Facade。如果不启用 withFacades,即使导入了 Illuminate\Support\Facades\File 也无法正常工作

$app->withEloquent() 方法实际上也启用了查询构建器。它注册了 DatabaseServiceProvider,而使用查询构建器则需要它。致谢

创建用户

进行用户数据库迁移

$ php artisan make:migration create_users_table --create=users
Enter fullscreen mode Exit fullscreen mode

找到迁移文件database/migrations/*_create_users_table.php并添加所需的表列(名称、电子邮件、密码);请参阅以下代码:

...
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique()->notNullable();
            $table->string('password');
            $table->timestamps();
        });
    }
...
Enter fullscreen mode Exit fullscreen mode

迁移数据库

$ php artisan migrate

Enter fullscreen mode Exit fullscreen mode

添加注册路由,顾名思义,用于注册用户。找到routes/web.php并插入所需代码,如下所示

// API route group
$router->group(['prefix' => 'api'], function () use ($router) {
   // Matches "/api/register
   $router->post('register', 'AuthController@register');

});
Enter fullscreen mode Exit fullscreen mode

由于我们要api在所有端点上添加前缀,为了减少重复,我们将使用路由分组来做到这一点。

此方法 ($router->post($uri, $callback);接受 $url 和 $callback 参数。在 中$callbackAuthController是我们的控制器类(我们将稍后创建此类)并且register是该类中的方法。

让我们创建我们的 AuthControler。

创建文件app/Http/Controllers/AuthController.php并用代码填充它,如下所示。


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use  App\User;

class AuthController extends Controller
{
    /**
     * Store a new user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function register(Request $request)
    {
        //validate incoming request 
        $this->validate($request, [
            'name' => 'required|string',
            'email' => 'required|email|unique:users',
            'password' => 'required|confirmed',
        ]);

        try {

            $user = new User;
            $user->name = $request->input('name');
            $user->email = $request->input('email');
            $plainPassword = $request->input('password');
            $user->password = app('hash')->make($plainPassword);

            $user->save();

            //return successful response
            return response()->json(['user' => $user, 'message' => 'CREATED'], 201);

        } catch (\Exception $e) {
            //return error message
            return response()->json(['message' => 'User Registration Failed!'], 409);
        }

    }


}
Enter fullscreen mode Exit fullscreen mode

使用路线注册一个用户(使用 POSTMAN)localhost:8000/api/register,您应该会得到一个成功的响应,如下所示

流明寄存器示例

用户登录

拉取JWT认证包。

$ composer require tymon/jwt-auth:dev-develop
Enter fullscreen mode Exit fullscreen mode

生成您的 API 密钥

$ php artisan jwt:secret
Enter fullscreen mode Exit fullscreen mode

config/auth.php使用以下配置创建文件

//config.auth.php

<?php

return [
    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    'guards' => [
        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => \App\User::class
        ]
    ]
];

Enter fullscreen mode Exit fullscreen mode

User对你的model( )进行一些修改app/User.php,以适应tymon/jwt-auth 的要求。请留意所有包含“JWT”的内容。

<?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Laravel\Lumen\Auth\Authorizable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;


use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Model implements AuthenticatableContract, AuthorizableContract, JWTSubject
{
    use Authenticatable, Authorizable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email'
    ];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = [
        'password',
    ];




    /**
     * 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 [];
    }
}

Enter fullscreen mode Exit fullscreen mode

做一些改变bootstrap/app.php

//before
// $app->routeMiddleware([
//     'auth' => App\Http\Middleware\Authenticate::class,
// ]);

//After
$app->routeMiddleware([
    'auth' => App\Http\Middleware\Authenticate::class,
]);
Enter fullscreen mode Exit fullscreen mode
//before
 // $app->register(App\Providers\AppServiceProvider::class);
 // $app->register(App\Providers\AuthServiceProvider::class);
 // $app->register(App\Providers\EventServiceProvider::class);

//After
 // $app->register(App\Providers\AppServiceProvider::class);
 $app->register(App\Providers\AuthServiceProvider::class);
 // $app->register(App\Providers\EventServiceProvider::class);

 // Add this line
 $app->register(Tymon\JWTAuth\Providers\LumenServiceProvider::class);
Enter fullscreen mode Exit fullscreen mode

添加登录路由routes/web.php

// API route group
$router->group(['prefix' => 'api'], function () use ($router) {
     // Matches "/api/register
    $router->post('register', 'AuthController@register');

      // Matches "/api/login
     $router->post('login', 'AuthController@login');
});
Enter fullscreen mode Exit fullscreen mode

在 Controller 类中添加一个全局的 respondWithToken 方法app/Http/Controllers/Controller.php。这样我们就可以从任何其他控制器访问它。

   ...
  //import auth facades
  use Illuminate\Support\Facades\Auth;


  //Add this method to the Controller class
  protected function respondWithToken($token)
    {
        return response()->json([
            'token' => $token,
            'token_type' => 'bearer',
            'expires_in' => Auth::factory()->getTTL() * 60
        ], 200);
    }

Enter fullscreen mode Exit fullscreen mode

在您的 AuthController 类中添加登录方法app/Http/Controllers/AuthController.php

   ...

   //import auth facades
   use Illuminate\Support\Facades\Auth;

   ...

     /**
     * Get a JWT via given credentials.
     *
     * @param  Request  $request
     * @return Response
     */
    public function login(Request $request)
    {
          //validate incoming request 
        $this->validate($request, [
            'email' => 'required|string',
            'password' => 'required|string',
        ]);

        $credentials = $request->only(['email', 'password']);

        if (! $token = Auth::attempt($credentials)) {
            return response()->json(['message' => 'Unauthorized'], 401);
        }

        return $this->respondWithToken($token);
    }

Enter fullscreen mode Exit fullscreen mode

使用路由登录用户localhost:8000/api/login,您应该会得到如下成功响应:

Lumen 登录示例

已验证的路由

为了我们的压轴大戏,我们将制作一些经过验证的路线。

添加几条路线routes/web.php

...
// API route group
$router->group(['prefix' => 'api'], function () use ($router) {
    // Matches "/api/register
   $router->post('register', 'AuthController@register');
     // Matches "/api/login
    $router->post('login', 'AuthController@login');

    // Matches "/api/profile
    $router->get('profile', 'UserController@profile');

    // Matches "/api/users/1 
    //get one user by id
    $router->get('users/{id}', 'UserController@singleUser');

    // Matches "/api/users
    $router->get('users', 'UserController@allUsers');
});

...

Enter fullscreen mode Exit fullscreen mode

创建一个文件app/Http/Controllers/UserController.php并用这段优雅的代码填充它。

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use  App\User;

class UserController extends Controller
{
     /**
     * Instantiate a new UserController instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Get the authenticated User.
     *
     * @return Response
     */
    public function profile()
    {
        return response()->json(['user' => Auth::user()], 200);
    }

    /**
     * Get all User.
     *
     * @return Response
     */
    public function allUsers()
    {
         return response()->json(['users' =>  User::all()], 200);
    }

    /**
     * Get one user.
     *
     * @return Response
     */
    public function singleUser($id)
    {
        try {
            $user = User::findOrFail($id);

            return response()->json(['user' => $user], 200);

        } catch (\Exception $e) {

            return response()->json(['message' => 'user not found!'], 404);
        }

    }

}


Enter fullscreen mode Exit fullscreen mode

以下是对三个新添加的端点之一的调用示例

Lumen 用户示例

这是github 上完整代码的链接

完结啦!

我希望本文能对您有所帮助,并希望您能在不久的将来基于这些知识部署出色的 API。我也希望在评论区看到您的贡献。

再见。

文章来源:https://dev.to/ndiecodes/build-a-jwt-authenticated-api-with-lumen-2afm
PREV
使用 Express Validator 的简洁方法
NEXT
实施缓存策略:高性能 Web 应用程序的技术