Lumen 8.0 使用 Jwt 认证的 Api

Lumen 8.0 使用 Jwt 认证的 Api

源代码参考

安装lumen

composer create-project --prefer-dist laravel/lumen blog

拷贝配置

copy .env.example .env

启动

php -S localhost:83 -t public

生成APP_KEY

由于lumenkey:generate命令,所以需要创建文件

<?php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Str;
use Symfony\Component\Console\Input\InputOption;

class KeyGenerateCommand extends Command
{
    // 命令名
    protected $name = 'key:generate';
    // 描述
    protected $description = "Set the application key";
    // 执行
    public function handle() {
        $key = $this->getRandomKey();
        if ($this->option('show')){
            $this->line('<command>'.$key.'</command>');
            return;
        }
        $path = base_path('.env');
        if (file_exists($path)){
            file_put_contents($path, str_replace('APP_KEY='.env('APP_KEY'), 'APP_KEY='.$key, file_get_contents($path)));
        }
        $this->info("Application key [$key] set successfully.");
    }

    /**
     * @return string
     * 获取随机32key
     */
    protected function getRandomKey(){
        return Str::random(32);
    }

    protected function getOptions()
    {
        return [
            ['show', null, InputOption::VALUE_NONE, 'Simply display the key instead of modifying files.']
        ];
    }
}

添加命令到app/Console/Kernel.php文件中

<?php

namespace App\Console;

use App\Console\Commands\KeyGenerateCommand;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        KeyGenerateCommand::class
    ];
}

生成key

D:\phpstudy_pro\WWW\lumen>php artisan key:generate
Application key [wRtxrX9DZs8HlZ0WMERxHo43Mkjbev1l] set successfully.

修改配置

APP_NAME=Lumen
APP_ENV=local
APP_KEY=wRtxrX9DZs8HlZ0WMERxHo43Mkjbev1l
APP_DEBUG=true
APP_URL=http://localhost
APP_TIMEZONE=Asia/Shanghai

LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lumen
DB_USERNAME=root
DB_PASSWORD=phpTest1!

CACHE_DRIVER=file
QUEUE_CONNECTION=sync

安装jwt

composer require tymon/jwt-auth

配置启动文件

修改boostrap/app.php

<?php

require_once __DIR__.'/../vendor/autoload.php';

(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
    dirname(__DIR__)
))->bootstrap();

date_default_timezone_set(env('APP_TIMEZONE', 'UTC'));

$app = new Laravel\Lumen\Application(
    dirname(__DIR__)
);

$app->withFacades();

$app->withEloquent();

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->configure('app');

// 认证中间件
 $app->routeMiddleware([
     'auth' => App\Http\Middleware\Authenticate::class,
 ]);

// $app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);
// jwt注册
$app->register(\Tymon\JWTAuth\Providers\LumenServiceProvider::class);

$app->router->group([
    'namespace' => 'App\Http\Controllers',
], function ($router) {
    require __DIR__.'/../routes/api.php';
    require __DIR__.'/../routes/web.php';
});

return $app;

生成秘钥

php artisan jwt:secret

# 查看.env
JWT_SECRET=JGPUooBjSd2PI91nizCI10ZfI56yLsl9dg9GiUozf8pgjfOS9fPYeTpgVIJaSbBG

自定义响应格式

加载此文件,需要在composer.json添加一下代码

"autoload": {
        ...
        "files": [
            "app/Helpers/helper.php"
        ]
    },
<?php

/**
 * 响应格式
 */
if (!function_exists('resp')) {
    function resp($code = 200, $msg = '', $data = []) {
        return response()->json([
            'code'  => $code,
            'msg'   => $msg,
            'data'  => $data,
        ]);
    }
}

用户认证

使用make:migration 生成表

默认此文件已存在,如果不存在则创建

D:\phpstudy_pro\WWW\lumen>php artisan make:migration create_users_table --create=users
Created Migration: 2020_09_18_103745_create_users_table

定义表字段

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('username');
            $table->string('password');
            $table->string('email');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

数据迁移

D:\phpstudy_pro\WWW\lumen>php artisan migrate
Migrating: 2020_09_18_103745_create_users_table
Migrated:  2020_09_18_103745_create_users_table (280.89ms)
修改User模型
<?php

namespace App\Models;

use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Lumen\Auth\Authorizable;
use Tymon\JWTAuth\Contracts\JWTSubject;

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

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

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

    /**
     * @inheritDoc
     * 获取jwt中的用户标识
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * @inheritDoc
     * 获取jwt中的用户自定义字段
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}
配置认证guard

拷贝vendor/laravel/lumen-framework/config/auth.phpconfig/目录下,并修改如下:

<?php

return [

    'defaults' => [
        'guard' => env('AUTH_GUARD', 'api')
    ],

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

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

    'passwords' => [
        //
    ],

];
定义路由文件api.php
<?php
/** @var \Laravel\Lumen\Routing\Router $router */

// 创建用户和登录
$router->group([
    'prefix' => 'auth',
    'namespace' => 'Api',
], function () use ($router) {
    $router->post('/store', 'UserController@store');
    $router->post('/login', 'UserController@login');
    $router->get('/user', 'UserController@index');
    $router->get('/me', 'UserController@me');
    $router->get('/logout', 'UserController@logout');
});
创建UserController
<?php
namespace App\Http\Controllers\Api;

use App\Exceptions\Code;
use App\Exceptions\Msg;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;

class UserController extends Controller
{

    /**
     * UserController constructor.
     * 认证中间件,排除登录和注册
     */
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login','store']]);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * 所有用户
     */
    public function index() {
        $users = User::paginate(env('PAGINATE'));
        return resp(Code::Success, Msg::Success, $users);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * 登录
     */
    public function login(Request $request) {
        $message = [
            'username.required' => "请输入用户名",
            'password.required' => "请输入密码",
        ];
        $validator = Validator::make($request->all(), [
            'username' => 'required',
            'password'  => 'required'
        ], $message);
        if ($validator->fails()) {
            foreach($validator->errors()->getMessages() as $error) {
                return resp(Code::LoginFailed, $error[0]);
            }
        }
        $credentials = request(['username', 'password']);
        if (! $token = auth()->attempt($credentials)) {
            return resp(Code::LoginFailed, Msg::LoginFailed);
        }
        return resp(Code::LoginSuccess, Msg::LoginSuccess, $this->responseWithToken($token));
    }

    /**
     * @param $token
     * @return array
     * 返回token信息
     */
    protected function responseWithToken($token) {
        return [
            'access_token' => $token,
            'token_type'    => 'bearer',
            'expires_in'    => auth()->factory()->getTTL() * env('JWT_TTL')
        ];
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * 创建用户
     */
    public function store(Request $request)
    {
        $message = [
            'email.required'    => '请输入邮箱',
            'email.email'       => '邮箱格式不正确',
            'email.unique'      => '邮箱已存在',
            'username.required' => '请输入用户名',
            'password.required' => '请输入密码',
            'username.min'      => '用户名至少 :min 位',
            'password.min'      => '密码至少 :min 位',
        ];
        $validator = Validator::make($request->input(), [
            'email' => 'required|email|unique:users',
            'username' => 'required|min:6',
            'password' => 'required|min:8',
        ], $message);

        if ($validator->fails()) {
            foreach($validator->errors()->getMessages() as $error) {
                return resp(Code::CreateUserFailed, $error[0]);
            }
        }
        $username = $request->get('username');
        $email = $request->get('email');
        $password = $request->get('password');

        $attributes = [
            'email' => $email,
            'username' => $username,
            'password' => app('hash')->make($password)
        ];
        $user = User::create($attributes);
        return resp(Code::CreateUserSuccess, Msg::CreateUserSuccess, $user);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * 当前用户信息
     */
    public function me() {
        return resp(Code::UserIsMe, Msg::UserIsMe, auth()->user());
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * 退出登录
     */
    public function logout() {
        auth()->logout();
        return resp(Code::LoginOutSuccess, Msg::LoginOutSuccess);
    }

    /**
     * @return array
     * 刷新token
     */
    public function refresh(){
        return $this->responseWithToken(auth()->refresh());
    }
}
定义返回状态码和信息
<?php


namespace App\Exceptions;


class Code
{
    const   Success           = 200;
    const   Unauthorized      = 401;
    const   Failed            = 500;

    const   CreateUserSuccess = 10001;
    const   CreateUserFailed  = 10002;

    const   LoginSuccess      = 20001;
    const   LoginFailed       = 20002;
    const   LoginOutSuccess   = 20003;
    const   UserIsMe          = 20004;

    const   CreatePostsSuccess  =   30001;
    const   CreatePostsFailed   =   30002;
    const   PostsListSuccess    =   30003;
    const   PostsListFailed     =   30004;
}
<?php


namespace App\Exceptions;


class Msg
{
    const   Success           =   '成功';
    const   Unauthorized      =   '未认证';
    const   Failed            =   '失败';
    const   CreateUserSuccess =   '创建用户成功';
    const   CreateUserFailed  =   '创建用户失败';
    const   LoginSuccess      =   '登录成功';
    const   LoginFailed       =   '登录失败';
    const   LoginOutSuccess   =   '退出成功';
    const   UserIsMe          =   '获取当前用户';

    const   CreatePostsSuccess  =   '创建文章成功';
    const   CreatePostsFailed   =   '创建文章失败';
    const   PostsListSuccess    =   '查询文章列表成功';
    const   PostsListFailed     =   '查询文章列表失败';
}
测试创建用户

使用postman工具

创建用户
创建用户

登录用户
登录用户

当前用户
当前用户

用户列表
用户列表

退出登录
退出登录

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
39
粉丝
9
喜欢
71
收藏
102
排名:461
访问:1.9 万
私信
所有博文
社区赞助商