PHP之JWT的token登录认证
1.JWT简介
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
2 JSON Web Token的应用场景
Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。
单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。
3 JWT的原理
服务器认证以后,生成一个JSON格式的对象,发回给客户端,比如下面的这段json格式。
{
"用户名": "admin",
"角色": "超级管理员",
"到期时间": "2020-07-13 00:00:00"
}
以后客户端与服务端通信的时候,都要发回这个 JSON 对象。服务器靠这个json对象认定用户的身份。
为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名,显得更加安全。
这个时候的服务器不再保存任何 session 数据,也就是服务器变成无状态了,从而比较容易实现扩展。
4.JWT的数据结构
实际的 JWT是一个很长的字符串,中间用点(.)分隔成三个部分。就像下面这样:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImp0aSI6IjNmMmc1N2E5MmFhIn0.eyJpYXQiOjE1NjI4
MzM0MDgsImlzcyI6Imh0dHA6XC9cL3d3dy5weWcuY29tIiwiYXVkIjoiaHR0cDpcL1wvd3d3LnB5Zy5j
b20iLCJuYmYiOjE1NjI4MzM0MDcsImV4cCI6MTU2MjkxOTgwOCwianRpIjoiM2YyZzU3YTkyYWEiLCJ1
c2VyX2lkIjoxfQ.NFq1qQ-Z5c4pwit8ZkyWEwX6SBXmnHJcc6ZDgSD5nhU
JWT的三个部分依次如下:
- Header(头部)
- Payload(负载)
- Signature(签名)
5.JWT的使用方式
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存localStorage。
此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面
6.JWT的几个特点
1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
2)JWT 不加密的情况下,不能将秘密数据写入 JWT。
3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
7 基于Token的身份认证 与 基于服务器的身份认证
在讨论基于Token的身份认证是如何工作的以及它的好处之前,我们先来看一下以前我们是怎么做的:
HTTP协议是无状态的,也就是说,如果我们已经认证了一个用户,那么他下一次请求的时候,服务器不知道我是谁,我们必须再次认证
传统的做法是将已经认证过的用户信息存储在服务器上,比如Session。用户下次请求的时候带着Session ID,然后服务器以此检查用户是否认证过。
这种基于服务器的身份认证方式存在一些问题:
Sessions : 每次用户认证通过以后,服务器需要创建一条记录保存用户信息,通常是在内存中,随着认证通过的用户越来越多,服务器的在这里的开销就会越来越大。
Scalability : 由于Session是在内存中的,这就带来一些扩展性的问题。
CORS : 当我们想要扩展我们的应用,让我们的数据被多个移动设备使用时,我们必须考虑跨资源共享问题。当使用AJAX调用从另一个域名下获取资源时,我们可能会遇到禁止请求的问题。
CSRF : 用户很容易受到CSRF攻击。
JWT与Session的差异
相同点是,它们都是存储用户信息;然而,Session是在服务器端的,而JWT是在客户端的。
Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销。而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。
Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。
基于Token的身份认证是如何工作的
基于Token的身份认证是无状态的,服务器或者Session中不会存储任何用户信息。
没有会话信息意味着应用程序可以根据需要扩展和添加更多的机器,而不必担心用户登录的位置。
虽然这一实现可能会有所不同,但其主要流程如下:
用户携带用户名和密码请求访问 -服务器校验用户凭据 -应用提供一个token给客户端 -客户端存储token,并且在随后的每一次请求中都带着它 -服务器校验token并返回数据。
用Token的好处
无状态和可扩展性:Tokens存储在客户端。完全无状态,可扩展。我们的负载均衡器可以将用户传递到任意服务器,因为在任何地方都没有状态或会话信息。
安全:Token不是Cookie。(The token, not a cookie.)每次请求的时候Token都会被发送。而且,由于没有Cookie被发送,还有助于防止CSRF攻击。即使在你的实现中将token存储到客户端的Cookie中,这个Cookie也只是一种存储机制,而非身份认证机制。没有基于会话的信息可以操作,因为我们没有会话!
还有一点,token在一段时间以后会过期,这个时候用户需要重新登录。这有助于我们保持安全。还有一个概念叫token撤销,它允许我们根据相同的授权许可使特定的token甚至一组token无效。
实现:
[安装]
composer require lcobucci/jwt 3.3 <?php
namespace tools\jwt; use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData; class Token
{
private static $_config = [
'audience' => 'receiver',//接收人
'id' => '20220811',//token的唯一标识,这里只是一个简单示例
'sign' => 'G7qWzjsNlUaWNhJ1',//签名密钥
'issuer' => '',//签发人
'expire' => 3600*24 //有效期(24小时)
]; //生成token
public static function getToken($user_id){ //签名对象
$signer = new Sha256();
//获取当前时间戳
$time = time();
//设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、签名
$token = (new Builder())->issuedBy(self::$_config['issuer'])
->canOnlyBeUsedBy(self::$_config['audience'])
->identifiedBy(self::$_config['id'], true)
->issuedAt($time)
->canOnlyBeUsedAfter($time-1)
->expiresAt($time + self::$_config['expire'])
->with('user_id', $user_id)
->sign($signer, self::$_config['sign'])
->getToken();
return (string)$token;
} //从请求信息中获取token令牌
public static function getRequestToken()
{
if (empty($_SERVER['HTTP_AUTHORIZATION'])) {
return false;
} $header = $_SERVER['HTTP_AUTHORIZATION'];
$method = 'bearer';
//去除token中可能存在的bearer标识
return trim(str_ireplace($method, '', $header));
} //从token中获取用户id (包含token的校验)
public static function getUserId($token = null)
{
$user_id = null; $token = empty($token)?self::getRequestToken():$token; if (!empty($token)) {
//为了注销token 加以下if判断代码
$delete_token = cache('delete_token') ?: [];
if(in_array($token, $delete_token)){
//token已被删除(注销)
return $user_id;
}
$token = (new Parser())->parse((string) $token);
//验证token
$data = new ValidationData();
$data->setIssuer(self::$_config['issuer']);//验证的签发人
$data->setAudience(self::$_config['audience']);//验证的接收人
$data->setId(self::$_config['id']);//验证token标识 if (!$token->validate($data)) {
//token验证失败
return $user_id;
} //验证签名
$signer = new Sha256();
if (!$token->verify($signer, self::$_config['sign'])) {
//签名验证失败
return $user_id;
}
//从token中获取用户id
$user_id = $token->getClaim('user_id');
} return $user_id;
}
}
JWT的参数解释
| 名称 | 解释 |
|---|---|
| iss (issuer) | issuer 请求实体,可以是发起请求的用户的信息,也可是jwt的签发者 |
| sub (Subject) | 设置主题,类似于发邮件时的主题 |
| aud (audience) | 接收jwt的一方 |
| exp (expire) | token过期时间 |
| nbf (not before) | 当前时间在nbf设定时间之前,该token无法使用 |
| iat (issued at) | token创建时间 |
| jti (JWT ID) | 对当前token设置唯一标示 |
相关类库支持:
PHP之JWT的token登录认证的更多相关文章
- 基于JWT的Token登录认证(一)
1.JWT简介 JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案. session登录认证方案:用户从客户端传递用户名.密码等信息,服务端认证后将信息存储在session中 ...
- 个人博客开发之blog-api 项目整合JWT实现token登录认证
前言 现在前后端分离,基于session设计到跨越问题,而且session在多台服器之前同步问题,肯能会丢失,所以倾向于使用jwt作为token认证 json web token 导入java-jwt ...
- 基于JWT的Token登录认证
1.JWT简介 JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案. 2.JWT的原理 JWT的原理是,服务器认证以后,生成一个JSON格式的对象,发回给客 ...
- ASP.NET WebApi 基于JWT实现Token签名认证
一.前言 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebServi ...
- ASP.NET Web API 2系列(四):基于JWT的token身份认证方案
1.引言 通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证.验证方式非常多,本 ...
- 基于jwt的用户登录认证
最近在app的开发过程中,做了一个基于token的用户登录认证,使用vue+node+mongoDB进行的开发,前来总结一下. token认证流程: 1:用户输入用户名和密码,进行登录操作,发送登录信 ...
- 基于JWT的token身份认证方案
一.使用JSON Web Token的好处? 1.性能问题. JWT方式将用户状态分散到了客户端中,相比于session,可以明显减轻服务端的内存压力. Session方式存储用户id的最大弊病在于S ...
- 基于JWT的token身份认证方案(转)
https://www.cnblogs.com/xiangkejin/archive/2018/05/08/9011119.html 一.使用JSON Web Token的好处? 1.性能问题. JW ...
- 【项目实践】一文带你搞定Session和JWT的登录认证方式
以项目驱动学习,以实践检验真知 前言 登录认证,估计是所有系统中最常见的功能了,并且也是最基础.最重要的功能.为了做好这一块而诞生了许多安全框架,比如最常见的Shiro.Spring Security ...
- ASP.NET WebApi 基于OAuth2.0实现Token签名认证
一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将是我们需要思考的问题.为了保护我们的WebApi数 ...
随机推荐
- 【Azure Policy】使用deployIfNotExists 把 Azure Activity logs 导出保存在Storage Account
问题描述 使用Azure Policy,对订阅下的全部Activity Log配置Diagnostic Setting,要求: 在Subscription或Management Group级别,针对未 ...
- 【JS设计模式笔记】神奇的魔术师-简单工厂模式(创建型)
简单工厂模式(Simple Factory):又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例.主要用来创建同一类对象. 第一次需求 开发一个登录模块的需求,用户名输入框如果输入的内容不 ...
- JVM(JAVA Virtual Machine)Java虚拟机
JVM的跨平台性 一次编写,到处运行 JVM将字节码文件编译成对应操作系统的机器码 JVM的语言无关性 JVM的内存区域 虚拟机栈:在JVM运行过程中存储当前线程运行方法所需的数据,指令.返回地址 本 ...
- 【QT性能优化】QT性能优化之QT6框架高性能网络编程框架实现百万TCP长连接网络服务器:QT是否适合做高性能网络应用?补天云这个视频告诉你在大厂Linux云服务器上的实测结果
QT性能优化之QT6框架高性能网络编程框架实现百万TCP长连接网络服务器 Ø 简介 本文作者编写了一套基于QT的TCP网络服务器程序和基于QT的TCP客户端程序,在某大厂的云服务器上进行了C1000K ...
- acme+cloudflare生成免费证书(自动续期)
acme DNSapi acme DNSapi的作用是在申请证书时使用dns交易,acme可以通过dnsapi在对应的dns管理平台提交对应的dns记录.玩过证书的朋友都知道,证书申请时有三种验证方式 ...
- SelMatch:最新数据集蒸馏,仅用5%训练数据也是可以的 | ICML'24
数据集蒸馏旨在从大型数据集中合成每类(IPC)少量图像,以在最小性能损失的情况下近似完整数据集训练.尽管在非常小的IPC范围内有效,但随着IPC增加,许多蒸馏方法变得不太有效甚至性能不如随机样本选择. ...
- Nuxt.js 应用中的 app:suspense:resolve 钩子详解
title: Nuxt.js 应用中的 app:suspense:resolve 钩子详解 date: 2024/10/6 updated: 2024/10/6 author: cmdragon ex ...
- .NET使用Graphql的演示
Graphql是什么?先来一段AI给的回答: GraphQL是一种为API设计的查询语言,与REST相比,它提供了更高效.强大和灵活的方法来与数据交互.GraphQL由Facebook于2012年开发 ...
- K8s GPU 资源管理探索:在 KubeSphere 上部署 AI 大模型 Ollama
作者:运维有术星主 随着人工智能.机器学习.AI 大模型技术的迅猛发展,我们对计算资源的需求也在不断攀升.特别是对于需要处理大规模数据和复杂算法的 AI 大模型,GPU 资源的使用变得至关重要.对于运 ...
- 五分钟一百行代码,手写一个vue项目全局通用的toast提示组件
前言: 我们已经分享过如何快速实现自己需要的全局弹框组件: 在开发 Vue 项目时,特别是H5页面的项目,还有一个组件是我们非常常用的,它相对弹框来说没有那么大,并且不需要手动关闭在需要更简洁的提示用 ...