Laravel 中使用 JWT 作用户登录,身份认证

什么是JWT:

JWT 全名 JSON Web Token,是一种开放标准 (RFC 7519)。

用于在网络应用环境间安全地传输信息作为 JSON 对象。

它是一种轻量级的认证和授权机制,特别适合分布式系统的身份验证。

核心特点

  1. 紧凑格式:体积小,可通过URL、POST参数或HTTP头发送
  2. 自包含:包含所有必要信息,减少数据库查询
  3. 可验证:使用数字签名保证完整性
  4. 跨语言支持:几乎所有主流编程语言都有实现

JWT 的结构

由三部分组成,用点(.)分隔:

Header.Payload.Signature

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vZGV2LXNob3AtbWFuYWdlLWFwaS5ob21lLmtsZi5jb20vc2hvcC1hcGkvbG9naW4iLCJpYXQiOjE3NDM0MTM1NjcsImV4cCI6MTc0MzQxNzE2NywibmJmIjoxNzQzNDEzNTY3LCJqdGkiOiJUZjR1OENxRHB0dW9vTHZpIiwic3ViIjoiNDgwMyIsInBydiI6IjI3ZjQxNDY0MDE3YjAwZTE5MmIxNzUyNjMzNGJlNmI1ZGIwYTBkOTQifQ.5uRxjozQ89eK-zSPLF8aV2bKxWXpsJRgR5XmU9sCy3Q

工作流程

  1. 用户登录:客户端发送凭据到认证服务器
  2. 验证凭据:服务器验证后生成JWT
  3. 返回JWT:服务器将JWT返回给客户端
  4. 存储JWT:客户端存储JWT(通常localStorage或cookie)
  5. 携带JWT:客户端在请求头中发送JWT
Authorization: Bearer <token>
  1. 验证JWT:服务器验证JWT并授权访问

laravel 安装配置JWT

1.安装JWT包

composer require tymon/jwt-auth

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e5df5c6f62ed41e5aee53e68f09e9c8e.png

2.发布 JWT 配置文件

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

在这里插入图片描述
此时会在config 目录下生成 jwt.php 配置文件

3. 生成密钥

php artisan jwt:secret

这会在 .env 文件中添加 JWT_SECRET,注意的是 生产环境单独生成,为了安全

用户登录配置

1.用户模型配置

创建用户模型文件,必须继承 Authenticatable ,实现 两个方法 getJWTIdentifiergetJWTCustomClaims,必须的。

<?php

namespace App\Models;

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

class AdminUser extends Authenticatable implements JWTSubject
{
    // ... 其他代码
    
    /**
     * 获取JWT标识符
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * 获取JWT自定义声明
     */
    public function getJWTCustomClaims()
    {
        return [
            'role' => $this->role,  // 示例:添加用户角色到token
            // 可以添加更多自定义声明
        ];
    }
}

2.配置 auth.php

文件: config/auth.php

(2.1) 配置 Guard(守卫)

Guard 是 Laravel 认证系统的核心概念之一,它定义了:

  • 如何认证用户(使用什么驱动 driver)

    • session:传统的 web 应用认证方式(使用 cookies 和 session)

    • token:API 令牌认证(Laravel 自带的基础 token 认证)

    • jwt:使用 JWT 包提供的认证驱动

  • 从哪里获取用户信息(使用什么 provider

    • 指定使用哪个用户提供者(在 providers 数组中定义)

代码如下:

'guards' => [
    'web' => [
         'driver' => 'session',
         'provider' => 'users',
     ],
     //后台api守卫
     'admin-api' => [
         'driver' => 'jwt',  // 修改为 jwt 驱动
         'provider' => 'admin-user',  // 使用admin-user 作为 provider
     ],
 ],
  1. admin-api 是我定义的后台api的守卫
  2. driver驱动 设置JWT
  3. provider 用户提供者 用 admin-user
(2.2) 配置 providers (用户提供者)
'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'admin-user' => [
        'driver' => 'eloquent',
        'model' => AdminUser::class,
    ]
],
  1. admin-user 为前面引用的 用户提供者 名称
  2. driver 为 数据驱动
    • eloquent 驱动(最常用),使用 Eloquent ORM 从数据库获取用户
      • 使用 eloquent 驱动时,模型必须实现 Authenticatable 接口,具体看第一步
    • database 驱动,直接使用数据库查询构造器(非 Eloquent)
  3. model 为第一步定义的用户模型 AdminUser
(2.3) 配置 默认守卫
 'defaults' => [
        'guard' => 'admin-api',
        'passwords' => 'users',
    ],

passwords 配置项用于定义密码重置功能的相关设置。此文章不细说

3.登录控制器开发

login控制器有两种验证机制:

  1. 手动验证登录,auth 生成token【常用】
  2. 自动验证登录,生成token【注意密码】

手动验证登录

// 获取用户实例
$user = User::where('mobile', $request->mobile)->first();

// 手动验证密码
if (!Hash::check($request->password, $user->password)) {
    return response()->json(['error' => '密码错误'], 401);
}

// 生成Token的三种方式(任选其一)
// 方式1:直接通过用户实例生成
$token = JWTAuth::fromUser($user); 

// 方式2:使用auth辅助函数
$token = auth()->login($user); 

// 或者自定义claims
$token = JWTAuth::claims([
    'user_type' => $user->type,
    'exp' => now()->addDays(30)->timestamp // 自定义过期时间
])->fromUser($user); 

// 返回带Token的响应
return response()->json([
    'access_token' => $token,
    'token_type' => 'bearer',
    'user' => auth()->user(),
]);

上述就是登录验证 和 获取token 分离

  1. auth 为laravel的认证系统,使用默认守卫进行生成token
  2. auth()->user() 可获取到登录的用户信息

自动验证登录

// 验证输入
$validator = Validator::make($request->all(), [
     'mobile' => 'required|string|size:11', // 假设手机号是11位
     'password' => 'required|string|min:6',
 ]);

 if ($validator->fails()) {
     return response()->json([
         'status' => 'error',
         'message' => '参数验证失败',
         'errors' => $validator->errors()
     ], 422);
 }
 
// 使用手机号作为登录凭证
$credentials = $request->only('mobile', 'password');

$token = Auth::guard('admin-api')->attempt(['mobile' => $mobile, 'password' => $password, 'state' => 1]);
 if($token){
     $user = Auth::guard('admin-api')->user();
     return $this->success('登录成功', [
         'token' => $token,
         'user' => $user,
     ]);
 }else{
     return $this->error('您输入的账号或密码错误', 103);
 }

注意

使用 attempt 方法时,需要注意你的密码是否是用 Bcrypt 算法哈希,如果不是,则会有以下报错

This password does not use the Bcrypt algorithm.
在这里插入图片描述
原因Laravel 默认认证系统 Auth(包括 attempt() 方法)强制要求使用 Bcrypt 算法,只有Bcrypt 算法生成的密码,才能验证通过。

通过在 Hash Facade 上调用 make 方法来哈希密码

Hash::make($request->newPassword)

小结下:

  • 自动验证要求比较严格,但是也是有解决办法的。这里不过多说明,
  • 正常情况下。我是手动验证。然后生成token.。
  • 目前的遇到的验证,账号密码,手机号验证码等等。手动验证,灵活一点

4.前端构建请求

在这里插入图片描述

5.中间件补充

目录:app/Http/Middleware/UserCheckToken.php

<?php

namespace App\Http\Middleware;

use App\Http\Trait\ResponseJson;
use Closure;
use Tymon\JWTAuth\Facades\JWTAuth;

class UserCheckToken
{
    use ResponseJson;

    public function handle($request, Closure $next)
    {
        try{
            $user = auth()->user();
            if(!$user){
                return $this->error('用户未找到', 401);
            }
        }
        catch(\Exception $e){
            return $this->error('Token 验证失败', 401);
        }

        return $next($request);
    }

}

创建中间件 UserCheckToken

auth()->user() 的作用

  • 验证请求携带有效的 JWT Token(Authorization: Bearer xxx)
  • JWT 会自动解析 Token还原用户信息

注意:

  1. 同一次请求中多次调用 auth()->user() 不会重复查询数据库,第一次查询数据库,第二次返回内存缓存
  2. 缓存持续到当前 HTTP 请求结束下次请求会重新解析 Token。

6. 路由配置中间件

Route::middleware([UserCheckToken::class])->group(function(){
    Route::get('/test', [TestController::class, 'index']);
});

将需要验证登录信息的接口,放在此中间件下即可。

上述即完整的用Jwt 实现用户的登录。里面有很多的知识点都可以进行扩展,可以实现很多强大的,自定义的需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值