侧边栏壁纸
博主头像
AngusWong's博客 博主等级

行动起来,活在当下

  • 累计撰写 25 篇文章
  • 累计创建 26 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录
PHP

Lumen使用JWT用户认证

Administrator
2021-03-12 / 0 评论 / 0 点赞 / 10 阅读 / 0 字
Lumen用户认证主要是使用【API】的方式来进行认证,在实际开发中,我们不能只是简单的获取 api_token直接关联数据库查找用户信息。在 API 开发中,用户认证是核心,是数据是否有保障的前提,目前主要有两种常用方式进行用户认证: JWT 和 OAuth2。 这萹文章主要讲怎么使用tymon/jwt-auth来实现JWT认证 [h2title]一、安装引入jwt[/h2title]
composer require tymon/jwt-auth
速度慢的尝试切换阿里云镜像再执行(安装lumen应该已经配置过了)
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ 
[h2title]二、配置文件auth.php修改[/h2title]
Lumen 项目中,默认没有 config 文件夹,需要在项目根目录创建,并将 vendor 源代码中auth.php 复制出来,同时将 api 认证指定为 「jwt」
auth.php所在目录:
vendor/laravel/lumen-framework/config/auth.php
  • 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' => env('AUTH_GUARD', 'user'),
    ],

    /*
    |--------------------------------------------------------------------------
    | 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: "token"
    |
    */

    'guards' => [
        'user'      => [
            'driver'   => 'jwt',
            'provider' => 'users'
        ],
        'operator' => [
            'driver'   => 'jwt',
            'provider' => 'operators'
        ]
    ],

    /*
    |--------------------------------------------------------------------------
    | 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\User::class,
        ],
        'operators' => [
            'driver' => 'eloquent',
            'model'  => App\Operator::class,
        ]
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | Here you may set the options for resetting passwords including the view
    | that is your password reset e-mail. You may also set the name of the
    | table that maintains all of the reset tokens for your application.
    |
    | 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代表前台用户,operators代表后台管理用户,App\User是前台用户Model,App\Operator是后台管理用户Model App\User.php参考
<?php

namespace App;

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

/**
 * Class User
 * @property integer id 用户ID
 * @property string uname 登陆账号
 * @property string password 密码
 * @property string code 辅助加密
 * @property string nick 昵称
 * @property string head 用户头像
 * @property string realname 真实姓名
 * @property integer sex 性别
 * @property string state_code 国家码
 * @property string mobile 手机号
 * @property string email 电子邮箱
 * @property string birthday 生日
 * @property string last_ip 最后登陆IP
 * @package App
 */
class User extends Model implements AuthenticatableContract, AuthorizableContract, JWTSubject
{
    use Authenticatable, Authorizable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'nick', 'realname', 'state_code', 'mobile', 'birthday', 'sex'
    ];

    protected $casts
        = [
            'created_at'   => 'timestamp',
            'updated_at'   => 'timestamp',
        ];

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

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [
            'token' => $this->token,
        ];
    }

    public function toArray()
    {
        $arr = parent::toArray();
        if (!empty($this->head)) {
            $arr['head_img'] = url($this->head);
        }
        return $arr;
    }

}
App\Operator.php参考
<?php

namespace App;

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

/**
 * Class Operator
 * @package App
 * @property integer id 管理员ID
 * @property string username 管理员登陆账号
 * @property string password 密码
 * @property string code 辅助加密
 * @property string name 姓名
 * @property string mobile 电话
 * @property string email 邮箱
 * @property boolean super 是否超级管理员
 * @property integer role_id 角色ID
 * @property string last_ip 最后登陆IP
 * @property string memo 员工简介
 */
class Operator extends Model implements AuthenticatableContract, AuthorizableContract, JWTSubject
{
    use Authenticatable, Authorizable;
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name', 'mobile', 'email', 'super', 'role_id', 'last_ip', 'memo'];

    protected $casts
        = [
            'super'      => 'boolean',
            'created_at' => 'timestamp',
            'updated_at' => 'timestamp',
        ];

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

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [];
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function role()
    {
        return $this->belongsTo(Role::class);
    }
}
  [h2title]三、注册ServiceProvider:[/h2title] 1、在bootstrap/app.php中注册对应的Provider
$this->app->register(\Tymon\JWTAuth\Providers\LumenServiceProvider::class);
2、在bootstrap/app.php中打开配置withFacades,去掉$app->withFacades();前面的注释
$app->withFacades();
3、增加auth中间件
$app->routeMiddleware([
    'auth' => App\Http\Middleware\Authenticate::class,
]);
bootstrap/app.php代码参考:
<?php

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

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

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| Here we will load the environment and create the application instance
| that serves as the central piece of this framework. We'll use this
| application as an "IoC" container and router for this framework.
|
*/

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

$app->withFacades();

$app->withEloquent();

/*
|--------------------------------------------------------------------------
| Register Container Bindings
|--------------------------------------------------------------------------
|
| Now we will register a few bindings in the service container. We will
| register the exception handler and the console kernel. You may add
| your own bindings here if you like or you can make another file.
|
*/

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

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

/*
|--------------------------------------------------------------------------
| Register Config Files
|--------------------------------------------------------------------------
|
| Now we will register the "app" configuration file. If the file exists in
| your configuration driectory it will be loaded; otherwise, we'll load
| the default version. You may register other files below as needed.
|
*/

$app->configure('app');
$app->configure('translatable');

/*
|--------------------------------------------------------------------------
| Register Middleware
|--------------------------------------------------------------------------
|
| Next, we will register the middleware with the application. These can
| be global middleware that run before and after each request into a
| route or middleware that'll be assigned to some specific routes.
|
*/

 $app->middleware([
     App\Http\Middleware\CorsMiddleware::class
 ]);

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

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/
$app->register(Tymon\JWTAuth\Providers\LumenServiceProvider::class);
$app->register(Illuminate\Redis\RedisServiceProvider::class);
$app->register(Astrotomic\Translatable\TranslatableServiceProvider::class);
// $app->register(App\Providers\AppServiceProvider::class);
// $app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);

/*
|--------------------------------------------------------------------------
| Load The Application Routes
|--------------------------------------------------------------------------
|
| Next we will include the routes file so that they can all be added to
| the application. This will provide all of the URLs the application
| can respond to, as well as the controllers that may handle them.
|
*/

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

return $app;
  中间件App\Http\Middleware\Authenticate代码参考如下:
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Auth\Factory as Auth;

class Authenticate
{
    /**
     * The authentication guard factory instance.
     *
     * @var \Illuminate\Contracts\Auth\Factory
     */
    protected $auth;

    /**
     * Create a new middleware instance.
     *
     * @param  \Illuminate\Contracts\Auth\Factory  $auth
     * @return void
     */
    public function __construct(Auth $auth)
    {
        $this->auth = $auth;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if ($this->auth->guard($guard)->guest()) {
            return response('Unauthorized.', 401);
        }
        // 判断当前用户是否登录
        if ($this->auth->guard($guard)->check()) {
            $user = $this->auth->guard($guard)->user(); // 获取登陆信息
            \Illuminate\Support\Facades\Auth::setUser($user); // 设置Auth获取的用户信息
        }
        return $next($request);
    }
}
  [h2title]四、jwt需要生成secret,修改配置文件设置过期时间等参数[/h2title] 1、jwt需要生成secret,执行后会生成在.env文件中
php artisan jwt:secret
2、配置文件中配置过期时间等参数,如下
JWT_SECRET=lCWOhg***********************************G98VwvwE7l
#有效时间-单位:分钟 7天
JWT_TTL = 10080
#刷新时间-单位:分钟  默认 30天
JWT_REFRESH_TTL = 43200
#宽限时间 单位:秒
JWT_BLACKLIST_GRACE_PERIOD = 60
  [h2title]五、配置路由进行测试,这里使用后台用户测试[/h2title] routes/web.php 路由代码参考:
$router->group(['namespace' => 'Admin', 'prefix' => 'admin'], function () use ($router) {
    $router->post('login', ['name' => '管理员登陆', 'uses' => 'LoginController@login']);
    $router->group(['middleware' => 'auth:operator'], function () use ($router) {
        $router->get('operator', ['name' => '获取管理员信息', 'uses' => 'OperatorController@userinfo']);
    });
});
其中'middleware'=>'auth:operator'是设置后台管理的中间键 登陆控制器App\Http\Controllers\Admin\LoginController.php代码参考:
<?php


namespace App\Http\Controllers\Admin;


use App\Http\Lib\Result;
use App\Operator;
use Illuminate\Http\Request;
use Laravel\Lumen\Routing\Controller;
use Tymon\JWTAuth\Facades\JWTAuth;

class LoginController extends Controller
{
    /**
     * 用户登陆
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
        if ($request->has('username') && $request->has('password')) {
            $user = Operator::query()
                ->where('username', '=', $request->input('username'))
                ->first();
            if ($user == null) {
                return Result::error(Result::ERR_UNAME, '管理员账户不存在!');
            }
            if ($user && $user->password === md5($request->input('password') . $user->code)) {
                $user->last_ip   = $request->getClientIp();
                $user->save();
                $token = JWTAuth::fromUser($user);
                $formatToken = $this->formatToken($token);
                $formatToken['uuid'] = $user->username;
                return Result::success($formatToken);
            } else {
                return Result::error(Result::ERR_PWD, '密码错误');
            }
        } else {
            return Result::error(Result::ERR_PARAM, '登录信息不完整,请输入用户名和密码');
        }
    }

    /**
     * Get the token array structure.
     *
     * @param string $token
     *
     * @return array
     */
    protected function formatToken($token)
    {
        return [
            'access_token' => $token,
            'token_type'   => 'Bearer',
            'expires_in'   => time() + JWTAuth::factory()->getTTL() * 60
        ];
    }
}
  获取管理员信息的控制器App\Http\Controllers\Admin\OperatorController.php代码参考:
<?php


namespace App\Http\Controllers\Admin;

use App\Http\Lib\Result;
use App\Operator;
use Illuminate\Support\Facades\Auth;

class OperatorController extends AuthController
{
    /**
     * 获取用户信息
     * @return \Illuminate\Http\JsonResponse
     */
    public function userinfo()
    {
        $user = Auth::user();
        return Result::success($user);
    }

}
  [h2title]六、POSTMAN接口测试[/h2title] 1、登陆接口测试: 2、通过access_token获取管理员信息测试    
0

评论区