登陆需要的用户表:
php artisan make:migration create_admins_table --create=admins
运行后在database/migrations下生成2022_06_15_032902_create_admins_table.php文件,内容如下:

  1. <?php
  2. use Illuminate\Database\Migrations\Migration;
  3. use Illuminate\Database\Schema\Blueprint;
  4. use Illuminate\Support\Facades\Schema;
  5. class CreateAdminsTable extends Migration
  6. {
  7. /**
  8. * Run the migrations.
  9. *
  10. * @return void
  11. */
  12. public function up()
  13. {
  14. Schema::create('admins', function (Blueprint $table) {
  15. $table->id();
  16. $table->string('name');
  17. $table->string('phone')->unique();
  18. $table->string('password');
  19. $table->rememberToken();
  20. $table->timestamps();
  21. });
  22. }
  23. /**
  24. * Reverse the migrations.
  25. *
  26. * @return void
  27. */
  28. public function down()
  29. {
  30. Schema::dropIfExists('admins');
  31. }
  32. }

1.安装 Jwt-auth 扩展包。

composer require tymon/jwt-auth

2.安装完成后在配置文件config/app.php 中注册服务提供者和别名

'providers' => [
    ...
    Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
]

3.发布资源和配置,在config目录下会生成jwt.php配置文件

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

4.生成密钥,在.env文件中可以看到新增JWT_SECRET=secret

$ php artisan jwt:secret

5.配置Auth.php,在config/auth.php文件中,将guards/driver更新为jwt

可配置多个,后续认证通过auth(‘api’) 或auth(‘admin’)区分,
model标识:登陆所用的表

'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
    'admin' => [
      'driver' => 'jwt',
      'provider' => 'admins',
      'hash' => false,
    ],
    ...
],

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

         'admins' => [
             'driver' => 'eloquent',
             'model' => App\Admin::class,
         ],
    ],

6.修改model,使用jwt-auth作为用户认证,则需要修改User模型。在app/Admin.php

getJWTCustomClaims() 该方法可以将数据注入token中。

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;

class Admin extends Authenticatable implements JWTSubject
{
    use Notifiable;

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

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function getJWTIdentifier()
    {
        // TODO: Implement getJWTIdentifier() method.
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        // TODO: Implement getJWTCustomClaims() method.
        // return [];/*不添加数据*/

        $data = Crypt::encryptString(
              json_encode(
                array('phone'=>$this->phone,'name' => $this->name), 
                JSON_UNESCAPED_UNICODE
              )
          );
          return compact('data');
    }
}

7.自定义认证中间件

php artisan make:middleware RefreshToken
运行后,会在app/http/middleware中看到RefreshToken.php文件,需要注意的是记得在app/http/Kernel.php添加如下代码:

protected $routeMiddleware = [
  ...
  'refreshtoken' => \App\Http\Middleware\RefreshToken::class,
];

RefreshToken.php中间件代码如下:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
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)
    {
        // 检查此次请求中是否带有 token,如果没有则抛出异常。
        $this->checkForToken($request);
        // 使用 try 包裹,以捕捉 token 过期所抛出的 TokenExpiredException  异常
        try {
            // 检测用户的登录状态,如果正常则通过
            if ($this->auth->parseToken()->authenticate()) {
                return $next($request);
            }
            throw new UnauthorizedHttpException('jwt-auth', '未登录');
        } catch (TokenExpiredException $exception) {
            // 此处捕获到了 token 过期所抛出的 TokenExpiredException 异常,我们在这里需要做的是刷新该用户的 token 并将它添加到响应头中
            try {
                // 刷新用户的 token
                $token = $this->auth->refresh();
                // 使用一次性登录以保证此次请求的成功
                Auth::guard('admin')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']);
            } catch (JWTException $exception) {
                // 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
                throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
            }
        }
        // 在响应头中返回新的 token
        return $this->setAuthenticationHeader($next($request), $token);
        //return $next($request);
    }
}

8.使用jwt

8.1创建控制器

php artisan make:controller V2\AuthController
在app/http/controllers下,修改代码,如下:

<?php

namespace App\Http\Controllers\V2;

use App\Http\Controllers\Controller;
use App\Admin;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class AdminAuthController extends Controller
{
    //用户注册
    public function register(Request $request){
        $valid = Validator::make($request->all(), [
            'name' => 'required|string|unique:admins',
            'phone' => 'required|unique:admins',
            'password' => 'required|string|min:6|max:10',
        ]);
        if ($valid->fails()) {
            return array(
                'code' => 1,
                'message' => $valid->errors()->first(),
                'data' => []
            );
        }
        $user = new Admin();
        $user->name = $request->name;
        $user->phone = $request->phone;
        $user->password = bcrypt($request->password);
        $user->save();     //插入数据库,创建用户
        return $user;
    }

    //用户登录
    public function login(Request $request){
       $credentials = $request->only('phone', 'password');
        if (! $token = auth('admin')->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
        //return auth('api')->user();   //此处可以获取登录成功用户的信息,如账号,邮箱等
        return $this->respondWithToken($token);
    }

    /**
     * 退出登录
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout(){
        auth('admin')->logout();
        return response()->json(['message' => '退出成功!']);
    }

    /**
     * 获取用户信息
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function user()
    {
        $user = Admin::find(Auth::user()->id);
        return response([
            'status' => 'success',
            'data' => $user
        ]);
    }

    /**
     * Refresh a token.
     * 刷新token,如果开启黑名单,以前的token便会失效。
     * 值得注意的是用上面的getToken再获取一次Token并不算做刷新,两次获得的Token是并行的,即两个都可用。
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(auth('admin')->refresh());
    }

    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
        ]);
    }

}

8.2编写路由routes/api.php

Route::group(['prefix'=>'v2','namespace'=>'V2'],function ($r) {//第二版本
    $r->get('register','AdminAuthController@register'); //注册
    $r->post('login','AdminAuthController@login');   //登录
    $r->post('logout', 'AdminAuthController@logout');// 退出

    Route::middleware(['refreshtoken','jwt.auth'])->group(function($router) {
        //访问地址 api/v1/auth/user
        $router->get('auth/user', 'AdminAuthController@user');
        $router->get('auth/refresh', 'AdminAuthController@refresh');
    });
});

测试流程:**先注册、登陆时获取token,在通过token请求其他需要鉴权的接口。**