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,必须的。

<?phpnamespace 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

<?phpnamespace 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 实现用户的登录。里面有很多的知识点都可以进行扩展,可以实现很多强大的,自定义的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/75250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51. “闲转易”交易平台小程序(基于springbootvue)

目录 1.系统的受众说明 2 关键技术介绍 2.1 SSM框架 2.2 Java技术及架构介绍 2.3 MYSQL数据库 2.4微信小程序框架 2.5 B/S架构 3 需求分析与可行性分析 3.1功能需求分析 3.2 性能需求分析 3.3系统设计规则与运行环境 3.4系统流程分析 3.5 可行性分析 4 系统设计 …

【STM32】GPIO输入(按键)

目录 一、如何分辨GPIO输入使用什么电频二、输入抖动问题如何消抖三、示例代码 一、如何分辨GPIO输入使用什么电频 先看原理图 即可知道他的初始输入状态需要高电平 判断可知使用上拉输入 二、输入抖动问题如何消抖 电路图中, 按键输入有额外的电容电阻, 是为了消抖 消抖方…

【Android Studio】配置教程以及解决过程中的问题(详细版本)

目录 前言 一、下载安装 二、配置 三、简单使用 新建项目 创建默认项目 四、解决过程中的问题 前言 如果你目前不是第一次安装&#xff0c;那需要完全卸载它。 因为一般电脑卸载 Android Studio 时容易落下一堆配置文件没删&#xff0c;卸载不干净导致无用文件占用空间…

EtherNet/IP转ProfiNet协议转换网关驱动西门子PLC与流量计的毫秒级压力同步控制

一、案例背景 汽车涂装线的静电喷涂工艺对压缩空气流量稳定性要求极高。原系统中Alicat流量计与西门子PLC因协议差异无法联动&#xff0c;导致涂料浪费率高达8%。通过JM-EIPM-PN网关实现供气系统与PLC的深度集成。从而实现了EtherNet/IP转ProfiNet的通讯。 二、设备连接与配置…

如何从0-1的建设云上稳定性?

一、系统架构 整个系统包含了私有云和公有云两个节点。前端和服务端存在私有云和公有云两套系统交互&#xff0c;公有云上的系统为三方黑盒系统。 带着上面的五点风险和挑战&#xff0c;我们从前后端的视角整体制定优化策略和方案。 二、前端策略 作为钉钉的合作产品&#xff…

【学Rust写CAD】17 通用2D仿射变换矩阵结构体(matrix/generic.rs)

源代码 // matrix.rs use std::ops::{Add, Mul};use std::ops::{Add, Mul};/// 通用2D仿射变换矩阵&#xff08;元素仅需Copy&#xff09; #[derive(Clone, Copy, Debug, PartialEq)] pub struct Matrix<X, Y, Xx, Xy, Yx, Yy> {pub x: X, pub y: Y,pub xx: Xx, pub xy:…

Spring Boot @RequestParam 解析参数时的常见问题及解决方案

1&#xff0c;遇到的问题&#xff1a;将后端接口写完后我想通过PostMan进行简单的测试一下&#xff0c;一不小心就遇到了这样的情况&#xff1a; org.springframework.web.bind.MissingServletRequestParameterException: Required Integer parameter contractId is not prese…

Golang中间件的原理与实现

一. 什么是 Middleware&#xff1f; 中间件&#xff08;Middleware&#xff09; 是一种 高阶函数&#xff0c;它接受一个函数作为输入&#xff0c;并返回一个经过增强的函数。它的核心思想是通过函数的递归嵌套&#xff0c;动态地为函数添加功能。在 Golang 中&#xff0c;中间…

算法设计学习3

实验目的及要求&#xff1a; 1.加强对结构体的应用。 2.熟悉字符计数排序。 实验设备环境&#xff1a; 1.微型计算机 2.DEV C(或其他编译软件) 实验步骤&#xff1a; 任务&#xff1a;要求使用自定义函数来实现 输入一段文本&#xff0c;统计每个字符出现的次数&#xff0c;按…

Vue2和3的vue-router:生命周期、懒加载

Vue2 vue-router 在 Vue 2 中使用 vue-router 可以方便地管理单页面应用&#xff08;SPA&#xff09;中的路由。理解 vue-router 的生命周期和懒加载机制对于构建高效的 Vue 应用至关重要。以下是一些关键点和示例代码来帮助你理解这些概念。 Vue Router 的生命周期 vue-rou…

【408--考研复习笔记】计算机网络----知识点速览

目录 一、计算机网络体系结构 1.计算机网络的定义与功能&#xff1a; 2.网络体系结构相关概念&#xff1a; 3.OSI 七层模型与 TCP/IP 模型&#xff1a; 4.通信方式与交换技术&#xff1a; 电路交换 报文交换 分组交换 5.端到端通信和点到点通信&#xff1a; 6.计算机…

MySQL-- 多表查询的分类,SQL92与SQL99,7种JOIN的实现,SQL99语法的新特性

目录 一&#xff0c;多表查询的分类 角度1&#xff1a;等值连接 vs 非等值连接 角度2&#xff1a;自连接 vs 非自连接 角度3&#xff1a;内连接 vs 外连接 二&#xff0c;SQL92语法实现内连接&#xff1a;见上&#xff0c;略SQL92语法实现外连接&#xff1a;使用 -…

时间轮算法:原理、演进与应用实践指南

目录 1. 时间轮算法基础 1.1 什么是时间轮算法&#xff1f; 1.2 核心组成部分 2. 基本时间轮的实现机制 2.1 时间轮的构成要素 2.2 工作原理详解 3. 基本时间轮的局限性 3.1 时间范围限制问题 3.2 简单解决方案及其缺陷 4. 时间轮算法的演进 4.1 Round机制&#xff…

Unity 常见报错 定位和查找方法

1.控制台 直接看报错信息 2.打log 例子&#xff1a; for(int i 0;i < 8;i) {Debug.Log(i);//这是打的log,看看到底i是几的时候出问题gameObject.name strs[i];} 3.断点调试 &#xff08;1&#xff09;在你想打断点的行&#xff0c;左边空白处点击可以打断点&#xff…

第十八章:Python实战专题:北京市水资源数据可视化与图书馆书籍管理应用开发

今天我要和大家分享两个非常有趣的Python实战项目&#xff1a;一个是北京市2001-2017年水资源数据的可视化分析&#xff0c;另一个是图书馆书籍管理应用程序的开发。这两个项目都使用了Python的主流库&#xff0c;比如Pandas、Matplotlib和Tkinter&#xff0c;非常适合初学者学…

音视频基础(音视频的录制和播放原理)

文章目录 一、录制原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 二、播放原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 一、录制原理 这张图展示…

Nginx多域名HTTPS配置全攻略:从证书生成到客户端安装

一、业务背景 在现代Web开发中&#xff0c;HTTPS已成为保障数据传输安全的标准协议。特别是对于地图类API服务&#xff08;如高德地图&#xff09;&#xff0c;往往需要同时支持多个子域名&#xff08;如webapi.amap.com、restapi.amap.com等&#xff09;的HTTPS访问。传统方式…

Redis原理:rename命令

RENAME key newkey 将一个key重命名为新key&#xff0c;如果key不存在&#xff0c;则会返回异常。如果newKey已经存在&#xff0c;则会被覆盖&#xff0c;其实newKey会被显示的删除&#xff0c;所以如果newKey是一个大key&#xff0c;则会引起延迟。 源码 void renameCommand…

k8s污点与容忍

k8s污点与容忍 k8s污点管理常用命令effect标记值查看污点添加污点删除污点 node污点与容忍污点容忍yaml示例容忍放大基于污点的驱逐驱逐时排除指定服务 设置master调度设置master尽量不调度允许master节点调度pod恢复Master Only状态将node标记为不可调度状态(节点警戒)设置nod…

(BFS)题解:P9425 [蓝桥杯 2023 国 B] AB 路线

题解&#xff1a;P9425 [蓝桥杯 2023 国 B] AB 路线 题目传送门 P9425 [蓝桥杯 2023 国 B] AB 路线 一、题目描述 给定一个NM的迷宫&#xff0c;每个格子标记为A或B。从左上角(1,1)出发&#xff0c;需要移动到右下角(N,M)。移动规则是&#xff1a;必须交替走K个A格子和K个B…