🚀 我的第三个webman插件 webman/jwt 认证插件

Tinywan

简介

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。

JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

插件地址:https://www.workerman.net/plugin/10

认证&授权流程

截图

签名流程

  1. 用户使用用户名和口令到认证服务器上请求认证。

  2. 认证服务器验证用户名和口令后,以服务器端生成JWT Token,这个token的生成过程如下:

    • 认证服务器还会生成一个 Secret Key(密钥)
    • JWT HeaderJWT Payload分别求Base64。在Payload可能包括了用户的抽象ID和的过期时间
    • 用密钥对JWT签名 HMAC-SHA256(SecertKey, Base64UrlEncode(JWT-Header)+'.'+Base64UrlEncode(JWT-Payload))
  3. 然后把 base64(header).base64(payload).signature 作为 JWT token返回客户端。

  4. 客户端使用JWT Token向应用服务器发送相关的请求。这个JWT Token就像一个临时用户权证一样。

安装

composer require tinywan/jwt

使用

生成令牌

use Tinywan\Jwt\JwtToken;

$user = [
    'id'  => 2022, // 这里必须是一个全局抽象唯一id
    'name'  => 'Tinywan',
    'email' => 'Tinywan@163.com'
];
$token = JwtToken::generateToken($user);
var_dump(json_encode($token));

输出(json格式)

{
    "token_type": "Bearer",
    "expires_in": 36000,
    "access_token": "eyJ0eXAiOiJAUR-Gqtnk9LUPO8IDrLK7tjCwQZ7CI...",
    "refresh_token": "eyJ0eXAiOiJIEGkKprvcccccQvsTJaOyNy8yweZc..."
}

响应参数

参数 类型 描述 示例值
token_type string Token 类型 Bearer
expires_in int 凭证有效时间,单位:秒 36000
access_token string 访问凭证 XXXXXXXXXXXXXXXXXXXX
refresh_token string 刷新凭证(访问凭证过期使用 ) XXXXXXXXXXXXXXXXXXX

支持函数列表

1、获取当前uid

$uid = JwtToken::getCurrentId();

2、获取所有字段

$email = JwtToken::getExtend();

3、获取自定义字段

$email = JwtToken::getExtendVal('email');

4、刷新令牌(通过刷新令牌获取访问令牌)

$refreshToken = JwtToken::refreshToken();

5、获取令牌有效期剩余时长(单位:秒)

$exp = JwtToken::getTokenExp();

6、单设备登录。默认是关闭,开启请修改配置文件config/plugin/tinywan/jwt

'is_single_device' => true,

签名算法

JWT 最常见的几种签名算法(JWA):HS256(HMAC-SHA256)RS256(RSA-SHA256) 还有 ES256(ECDSA-SHA256)

JWT 算法列表如下

+--------------+-------------------------------+--------------------+
   | "alg" Param  | Digital Signature or MAC      | Implementation     |
   | Value        | Algorithm                     | Requirements       |
   +--------------+-------------------------------+--------------------+
   | HS256        | HMAC using SHA-256            | Required           |
   | HS384        | HMAC using SHA-384            | Optional           |
   | HS512        | HMAC using SHA-512            | Optional           |
   | RS256        | RSASSA-PKCS1-v1_5 using       | Recommended        |
   |              | SHA-256                       |                    |
   | RS384        | RSASSA-PKCS1-v1_5 using       | Optional           |
   |              | SHA-384                       |                    |
   | RS512        | RSASSA-PKCS1-v1_5 using       | Optional           |
   |              | SHA-512                       |                    |
   | ES256        | ECDSA using P-256 and SHA-256 | Recommended+       |
   | ES384        | ECDSA using P-384 and SHA-384 | Optional           |
   | ES512        | ECDSA using P-521 and SHA-512 | Optional           |
   | PS256        | RSASSA-PSS using SHA-256 and  | Optional           |
   |              | MGF1 with SHA-256             |                    |
   | PS384        | RSASSA-PSS using SHA-384 and  | Optional           |
   |              | MGF1 with SHA-384             |                    |
   | PS512        | RSASSA-PSS using SHA-512 and  | Optional           |
   |              | MGF1 with SHA-512             |                    |
   | none         | No digital signature or MAC   | Optional           |
   |              | performed                     |                    |
   +--------------+-------------------------------+--------------------+

   The use of "+" in the Implementation Requirements column indicates
   that the requirement strength is likely to be increased in a future
   version of the specification.

可以看到被标记为 Recommended 的只有 RS256 和 ES256。

对称加密算法

插件安装默认使用HS256对称加密算法。

HS256 使用同一个「secret_key」进行签名与验证。一旦 secret_key泄漏,就毫无安全性可言了。因此 HS256 只适合集中式认证,签名和验证都必须由可信方进行。

非对称加密算法

RS256 系列是使用 RSA 私钥进行签名,使用 RSA 公钥进行验证。

公钥即使泄漏也毫无影响,只要确保私钥安全就行。RS256 可以将验证委托给其他应用,只要将公钥给他们就行。

RS512

ssh-keygen -t rsa -b 4096 -E SHA512 -m PEM -P "" -f RS512.key
openssl rsa -in RS512.key -pubout -outform PEM -out RS512.key.pub

RS512

ssh-keygen -t rsa -b 4096 -E SHA354 -m PEM -P "" -f RS384.key
openssl rsa -in RS384.key -pubout -outform PEM -out RS384.key.pub

RS256

ssh-keygen -t rsa -b 4096 -E SHA256 -m PEM -P "" -f RS256.key
openssl rsa -in RS256.key -pubout -outform PEM -out RS256.key.pub

🚀 视频地址

不懂的同学可以了解一下视频,会有详细的说明哦

12382 49 14
49个评论

喵了个咪

想啥来啥,mark一波

  • 暂无评论
不可说

牛逼

  • 暂无评论
hsk99

compsoer安装 php版本 限制是否可以去掉,当前生产环境是 7.3 没用到 7.4

tianleijie

截图
截图
请问还需要配置什么么

  • Tinywan 2022-02-27

    webman/console 版本太低了,升级一下

tianleijie

截图

  • tianleijie 2022-02-23

    在config下面手动创建了一个

  • tianleijie 2022-02-23

    ok了

  • Tinywan 2022-02-23

    默认配置文件都是有的,就是使用的插件的app,如果没有,你看看是不是你的console这个插件的版本比较低。请更新到webman-framework1.2.2或者后续更高版本。更多参考:https://www.workerman.net/q/7871

Tinywan

默认配置文件都是有的,就是使用的插件的app,如果没有,你看看是不是你的console这个插件的版本比较低。更多参考:https://www.workerman.net/q/7871

截图

  • 暂无评论
wang5955616

在中间件里面使用为什么获取不到任何数据?
截图

  • Tinywan 2022-02-27

    已经封装好的,为啥要自己重新搞?

Tinywan

中间件获取

截图

更多参考:https://github.com/Tinywan/webman-admin

  • 暂无评论
xuehuli8210

expires_in int 凭证有效时间,单位:秒 36000

如何设置expires_in有效时间

  • Tinywan 2022-03-07

    修改配置文件 config/plugin/tinywan/jwt/app.php access令牌过期时间,单位秒

mayibanjia

Bearer验证中的凭证格式有误,中间必须有个空格
您好 提示这个是什么错误?

Tinywan

JWT使用Bearer验证

Bearer验证中的凭证称为BEARER_TOKEN,或者是access_token,它的颁发和验证完全由我们自己的应用程序来控制,而不依赖于系统和Web服务器,Bearer验证的标准请求方式如下:

Authorization: Bearer [BEARER_TOKEN]

可以看出Bearer验证 Bearer[BEARER_TOKEN] 中间是有个空格的

  • 暂无评论
llocry00

关于插件,我想问下,如果token已经过期,我还能通过getTokenExp 获取到负数的剩余时长吗?

  • Tinywan 2022-04-08

    不行,过期时间返回是一个正整数,必须在过期前获取是否小于等于0。否则或抛出一个异常

  • llocry00 2022-04-08

    单设备登录是通过redis实现的?

  • Tinywan 2022-04-08

    是的

  • llocry00 2022-04-09

    楼主,是否考虑增加jwt过期时间容错功能,譬如token过期后30秒或者1分钟内还能有效,这个可以解决并发和自动续期问题

  • Tinywan 2022-04-09

    感谢你的建议,你的token既然已经过期了,为什么还要在30秒或者1分钟内还能有效?这个是不是自相矛盾了。你的并发和自动续期问题可否详细说明一下

shall


生产环境使用php7.4报以上错误

xjx2580

请问token错误如何返回自己的message格式,而不是返回异常

  • 暂无评论
Tinywan

请问token错误如何返回自己的message格式,而不是返回异常?

1、通过官方异常处理(推荐)

class Handler extends ExceptionHandler
{
    public function render(Request $request, Throwable $e): Response
    {
        if ($e instanceof Tinywan\Jwt\Exception\JwtTokenException) {
            // 返回自己自定义的message格式
            return json([
                'code' => $e->getCode(),
                'msg' => $e->getMessage()
            ]);
        }
       // 处理其他异常
        return parent::render($request, $e);
    }
}

2、通过try catch捕捉

try {
    $uid = JwtToken::getCurrentId();
} catch (Tinywan\Jwt\Exception\JwtTokenException $exception) {
    // 返回自己自定义的message格式
    return json(['code' => 0,'message' => $exception->getMessage()]);
}
  • 暂无评论
wang5955616

后台管理和用户端的id有可能重复 怎么避免?

  • yzh52521 2022-04-20

    @wang5955616 试试我的多应用 https://www.workerman.net/plugin/45

  • Tinywan 2022-04-20

    生成令牌的时候增加一个自定义字段即可,如:origin,后台管理:origin =manage ,用户端:origin =user

  • wang5955616 2022-04-20

    如果获取token的时候,后台的id=1 用户端id=1 JwtToken::getCurrentId(); 获取的也是1 用自定义字段来判断是用户还是管理员嘛?

  • Tinywan 2022-04-20

    是的,通过获取扩展字段函数

    $role = Tinywan\Jwt\JwtToken::getExtendVal('role');

    例如我们是通过 is_admin 这个扩展表示获取当前登录用户的身份信息

    {
      "extend": {
        "uid": 2054654646,
        "is_admin": true,
        "role": "admin",
        "realname": "管理员"
      }
    }
xuehuli8210

如何设置不同的令牌过期时间!例如 前台用户过期10天 后台管理用户过期30分钟

alct

单点登录 刷新token 会报错

qiming

JWT 必须使用 Redis 存储嘛?

jnmcok

1.建议在配置文件中增加access_token令牌名称和refresh_token令牌名称的自定义,而不是现在现在固定的Authorization

2.刷新令牌的时机应该是在access_token过期后,并且refresh_token没过期之间,但目前即使refresh_token没过期,只要调用$exp = Tinywan\Jwt\JwtToken::getTokenExp();就会返回错误

  • Tinywan 2022-09-01

    第一个,没必要吧!

    第二个,只要调用$exp = Tinywan\Jwt\JwtToken::getTokenExp();就会返回错误。这个如何复现呢?

  • jnmcok 2022-09-01

    把配置文件中的'access_exp' => 12,设置时间短一点,'leeway' => 0,然后在方法中调用\Tinywan\Jwt\JwtToken::verify(),只要access_exp时间已过,不管refresh_exp过不过,都会直接返回“身份验证会话已过期,请重新登录!”。我现在的主要问题是,想在access_exp过期后,refresh_exp之前进行刷新TOKEN,如何实现??

  • jnmcok 2022-09-01

    关键问题是想判断一下token是否过期,一用verify判断就报错了

  • jnmcok 2022-09-01

    其实用getTokenExp判断,也要走verify,当token过期后,同样报错

晚安。

用户点击退出登陆,怎么使当前生成的access_token马上失效

  • Tinywan 2022-09-01

    开启单点登录,清除缓存即可

  • 晚安。 2022-09-01

    不开单点登陆,有办法做到么

  • Tinywan 2022-09-01

    有,需要自己实现,
    1、生成的access_token存储在缓存
    2、登录校验 access_token 是否存在缓存中
    3、退出登录时,清除缓存

jnmcok

jnmcok

在配置项中可否加上这么一项,refresh_token是返回客户端还是保存在服务器的缓存中,让开发者决定,因为每次请求都携带这个备用的refresh_token,会无味的增加网络传送量

  • Tinywan 2022-09-09

    这配置项是支持关闭 refresh_token 选项的。你要存在缓存意图是?

27149

is_single_device为true。重新生成token后原来的token还能用

  • Tinywan 2022-09-30

    你是哪个版本?

  • 27149 2022-09-30

    1.2

  • Tinywan 2022-09-30

    原来的token你是在哪里还能使用

  • 27149 2022-09-30

    同一个用户,第一次登录生成一个token,第二次登录生成一个token。两个token请求后台都能验证通过并且获取到用户信息

  • Tinywan 2022-10-01

    请更新到最新版本。composer require tinywan/jwt ^1.4.0

  • 27149 2022-10-03

    可以了,谢谢

sayal

怎么注销用户?我发现没有注销token,使token失效的方法

  • Tinywan 2022-10-08

    请更新到最新版本。composer require tinywan/jwt ^1.5.0。调用方法:Tinywan\Jwt\JwtToken::clear();

  • sayal 2022-10-09

    更新找不到1.5版本,只有最高1.4版本的,默认源没法更新,用了阿里和腾讯的,过段时间我再看看这些镜像源有没有同步吧

  • Tinywan 2022-10-09

    我这边没问题:

    E:\dnmp\www\webman-admin>composer require tinywan/jwt ^1.5.0
    ./composer.json has been updated
    Running composer update tinywan/jwt
    Loading composer repositories with package information
    https://repo.packagist.org could not be fully loaded (curl error 28 while downloading https://repo.packagist.org/packages.json: Operation timed out after 10010 milliseconds with 0 out o
    f 0 bytes received), package information was loaded from the local cache and may be out of date
    Updating dependencies
    Lock file operations: 0 installs, 1 update, 0 removals
    - Upgrading tinywan/jwt (dev-main b3cbde8 => v1.5.0)
    Writing lock file
    Installing dependencies from lock file (including require-dev)
    Package operations: 0 installs, 1 update, 0 removals
    - Downloading tinywan/jwt (v1.5.0)
    - Upgrading tinywan/jwt (dev-main b3cbde8 => v1.5.0): Extracting archive
    Generating autoload files
    30 packages you are using are looking for funding.
    Use the `composer fund` command to find out more!
  • Tinywan 2022-10-09

    推荐使用官方源

Mimi

刷新token报错
截图

  • Tinywan 2022-12-09

    使用刷新令牌,而不是访问令牌去刷新

xiaoyaoboy

刷新令牌的时候,始终返回“身份验证令牌已失效”错误。看了下代码,发现是RedisHandler.php 里verifyToken()函数里这段代码,
if (Redis::get($cacheKey) != $token) {
throw new JwtCacheTokenException('身份验证令牌已失效');
}
Redis::get($cacheKey) 获取到的是保存在redis里的 access_token值。$token 是刷新请求头里传过来的refresh_token。结果就是比对结果永远不会相等。
我是在请求头里把access_token值换成refresh_token来调用刷新令牌接口的。

  • Tinywan 2022-12-15

    刷新令牌就是请求头efresh_token来调用刷新令牌接口的。

  • xiaoyaoboy 2022-12-15

    开了单点登录,用refresh_token刷新令牌,总是返回“身份验证令牌已失效”错误。然后,就把JwtToken.php里verifyToken()函数最后一个判断是否单点登录改成了这样
    if ($config['is_single_device'] && self::ACCESS_TOKEN == $tokenType)。
    在 refreshToken() 函数返回语句前添加判断是单点登录,是就将刷新后的token写入redis。
    if ($config['is_single_device']) {
    RedisHandler::generateToken([
    'id' => $extend['extend']['id'],
    'access_token' => $newToken['access_token'],
    'cache_token_ttl' => $config['cache_token_ttl'],
    'cache_token_pre' => $config['cache_token_pre']
    ]);
    }
    这样刷新token就可以正常返回,刷新后的token也会写入redis。旧的token失效,新的token也可以正常使用。是不是我的调用方法不对,没改之前,单点登录刷新token一直返回上面的错误。关闭单点登录后,可以成功调用刷新token。

  • Tinywan 2022-12-16

    感谢反馈,请更新到最新版本 v1.5.3

  • xiaoyaoboy 2022-12-16

    已经更新到v1.5.3。单点登录,刷新接口可以正常返回token。但是刷新后用新的token调用接口无效,看了下是redis里面保存的还是旧的token,新生成的token并没有保存并替换redis里的旧token,所以验证token总是失败。

  • Tinywan 2022-12-17

    感谢反馈,问题已找到,开启单点登录,刷新新临牌没存储的Redis,问题已解决。请更新到最新版本 v1.6.0

jacknum1

大佬 我插件应用请求的时候有些路由不需要校验JWT,如何实现呢?

  • Tinywan 2023-05-10

    不要走这个中间件就行了

  • jacknum1 2023-05-18

    已经解决了 不获取用户信息就行

siwei

https://github.com/Tinywan/webman-admin

克隆项目

git clone git@github.com:Tinywan/webman-admin.git


E:\phpstudy_pro\WWW\4>git clone git@github.com:Tinywan/webman-admin.git
Cloning into 'webman-admin'...
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
怎么安装不了。

用https://github.com/Tinywan/webman-admin 下载压缩包,

进入目录

cd webman-admin

安装依赖

composer install


前端安装

安装依赖

npm i 有如下错误:

Tinywan

本地云效没有任何问题

截图

  • 暂无评论
白鹄

支持 ~ 项目中都在使用

  • 暂无评论
evoxwht

JwtToken::clear()方法使用了之后,还是能通过JwtToken::getExtend()获取到用户信息
截图

  • Tinywan 2023-06-01

    配置文件的 'is_single_device' 这个开启没?

小W
  1. 没有开启单点登录时,clear()是无效的,源代码:
    截图

  2. 在 refreshToken 后,原token依旧生效,且保持原有效期不变;
    refreshToken后生成了新的access_token和refresh_token, 客户端就需要使用新的token请求,并不是将原token有效期增长/重置。

是这么理解吧

geek2bin

想问一下 websocket 应该如何验证jwt? ws server 是 webman/gateway-worker

  • Tinywan 2023-06-05

    目前只支持http,websocket 的话一般都是使用签名解决的

  • Tinywan 2023-06-05

    以下可以作为参考

    $gateway->onConnect = function($connection)
    {
        $connection->onWebSocketConnect = function($connection , $http_header)
        {
            // 判断连接来源是否合法,不合法就关掉连接(Jmeter压测暂时注释掉)
            if (!isset($_SERVER['HTTP_ORIGIN'])) {
                return $connection->close();
            }
    
            if (false === \redis\RedisHandler::isValidDomain($_SERVER['HTTP_ORIGIN'])) {
                return $connection->close();
            }
    
            if (!isset($_GET['sign']) || !isset($_GET['ts'])) {
                return $connection->close();
            }
    
            // 判断请求中的失效时间(timestamp+有效时长)是否小于当前时间
            if ($_GET['ts'] < time()) {
                return $connection->close();
            }
    
            $wsServerSign = sha1($_GET['ts'].'|'.config('security')['websocket']['secret']);
            if ($_GET['sign'] != $wsServerSign) {
                return $connection->close();
            }
        };
    }; 
  • geek2bin 2023-06-05

    这仅仅只是验证了下 请求的合法性,没包含用户身份信息。

  • geek2bin 2023-06-05

    getTokenFromHeaders 不考虑搞个姊妹方法?类似于getTokenFromGet ?
    这样在websocket请求的时候,可以在url中构造进去token,然后共用一套鉴权方案

  • geek2bin 2023-06-05

    如果从headers中没取到,尝试从get中取一下 token

  • geek2bin 2023-06-05

    或者 verifyToken 直接公共出来,可以手动验证token . 自由度大一点

  • 小W 2023-06-05

    应该可以使用jwt,因为ws握手是使用的http协议,所以在客户端请求链接时携带token就行

  • Tinywan 2023-06-05

    欢迎提交PR

  • 小W 2023-06-05

    verify方法可以直接传递token

  • geek2bin 2023-06-05

    是的,我看到了,我就用了verify

  • geek2bin 2023-06-05

    之前本来想着能够完美兼容就好,但是发现实际上在gateway-woker 中 上下文中根本就没有Request 对象,要想用getCurrentId那一套的话,需要自己new 一个 request(buffer),自己填充buffer (token 信息),然后Context set 实际上也是可行的

晚安。

这个能不能加一个手动传入authorization 值,有些地方这个值他不是从头部传过来的

$userinfo = \Tinywan\Jwt\JwtToken::getUser();
JackDx

1、可以支持指定个数单点登录嘛,比如说app和H5两个端?
2、因为JWT是明文 那extend里面信息就看的到或者id可以是加密的字符串吗?必须是数字吗
3、不用redis就没有办法单点注销嘛,我想从后台强制其中一个用户中里一个app强制注销?

爱吃鱼

截图
这里的异常信息返回的code都等于0, 在中间件try catch时不好判断jwt验证失败原因。建议不同的错误信息返回不同的code码,方便前端判断。 eg:返回405登录状态失效

  • Tinywan 2023-08-16

    code码是业务状态码。这个异常数据http层面的,统一是401

  • 爱吃鱼 2023-08-16

    不能统一返回401吧, 如果有token过期需要前端调用刷新token接口都返回401无法判断吧

  • Tinywan 2023-08-16

    http的状态码是可以支持自定义的,在配置文件

            // 自定义HTTP状态码
            'status' => [
                'validate' => 400, // 验证器异常
                'jwt_token' => 401, // 认证失败
                'jwt_token_expired' => 403, // 访问令牌过期
                'jwt_refresh_token_expired' => 402, // 刷新令牌过期
                'server_error' => 500, // 服务器内部错误
            ],
  • Tinywan 2023-08-16

    默认都是401,

  • 爱吃鱼 2023-08-16

    这个http状态在哪里配置的?

  • 爱吃鱼 2023-08-16

    目前我是通过在中间件里
    try {
    $accessUserId = \Tinywan\Jwt\JwtToken::getCurrentId();
    $response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
    } catch (\Tinywan\Jwt\Exception\JwtTokenExpiredException $exception) {//token过期
    // 返回自己自定义的message格式
    $msg = $exception->getMessage();
    $code = 401;
    $response = json([
    'code' => $code,
    'msg' => $msg,
    'data' => []
    ]);
    } catch (\Tinywan\Jwt\Exception\JwtRefreshTokenExpiredException $exception) {//提交的刷新token验证失败
    // 返回自己自定义的message格式
    $msg = $exception->getMessage();
    $code = 403;
    $response = json([
    'code' => $code,
    'msg' => $msg,
    'data' => []
    ]);
    }

  • Tinywan 2023-08-16

    你这写的太复杂话了,一个简单的中间件就可以搞定

  • Tinywan 2023-08-16

    使用这个异常插件,搞定一切:https://www.workerman.net/plugin/16

清梦独行

多表登录的话。is_single_device就用不了是吗,我看缓存里面是根据id来的。如果后台和前台用户同一个id这里是会出问题吧

  • Tinywan 2023-09-09

    单设备登录支持定义客户端 client 字段,自定义客户端单点登录(默认为WEB,即网页端),如:MOBILE、APP、WECHAT、WEB、ADMIN、API、OTHER等等

    $user = [
        'id'  => 2022,
        'name'  => 'Tinywan',
        'client' => 'MOBILE',
    ];
    $token = Tinywan\Jwt\JwtToken::generateToken($user);
    var_dump(json_encode($token));
  • Tinywan 2023-09-09

    你可以使用前台 'client' => 'FRONTEND', 后台 'client' => 'BACKEND',

  • 清梦独行 2023-09-10

    好的,我试试

aspire

  • Tinywan 2023-10-09

    这是你包依赖问题,本地php没开启sodium扩展

晚安。

'is_single_device' 这个是true
截图
最新版本测试
\Tinywan\Jwt\JwtToken::clear();
清除后,原token还是可以使用没有被删除

  • Tinywan 2023-10-31

    感谢反馈,多了一个:。请更新到v1.8.3

晚安。

截图

  • 暂无评论
leoxml
$cacheKey = $pre . $client. ':'. $uid;
$key = Redis::keys($cacheKey . '*');
if (!empty($key)) {
    Redis::del(current($key));
}
Redis::setex($cacheKey, $ttl, $token);

假设当前用户ID=1,$cacheKey = 'JWT:TOKEN:WEB:1'keys JWT:TOKEN:WEB:1*会匹配到JWT:TOKEN:WEB:10JWT:TOKEN:WEB:100等,del时岂不把别人的token删除了

小叽叽叽叽

我开启了单设备登录的is_single_device,但是我在两个浏览器里面,登录,其中一个并不会退出,refresh_token,还是可以依旧的刷新token,导致两边刷新都会同时在线,这个是要我在刷新中进行判断还是咋

      $tokens = JwtToken::refreshToken();
        return success([
            'access_token' => "Bearer " . $tokens['access_token'],
            'refresh_token' => "Bearer " . $tokens['refresh_token']
        ], "刷新成功");
  • 小叽叽叽叽 2023-11-17

    我调试发现,这个JwtToken,没有在
    /**

    • @desc: 校验令牌
    • @param string $token
    • @param int $tokenType
    • @return array
    • @author Tinywan(ShaoBo Wan)
      */
      private static function verifyToken(string $token, int $tokenType): array
      {
      $config = self::_getConfig();
      JWT::$leeway = $config['leeway'];
      $decoded = JWT::decode($token, new Key($publicKey, $config['algorithms']));
      $decodeToken = json_decode(json_encode($decoded), true);
      if ($config['is_single_device'] && self::ACCESS_TOKEN == $tokenType) {

          $client = $decodeToken['extend']['client'] ?? self::TOKEN_CLIENT_WEB;
          RedisHandler::verifyToken($config['cache_token_pre'], $client, (string)$decodeToken['extend']['id'], $token);
      }
      return $decodeToken;

      }
      这个方法里面进行验证是否是有效的,

  • 小叽叽叽叽 2023-11-17

    额,我改了一下把refresh_token存到了redis里面,进行和access_token一样的判断,就是还有一个问题,刷新以后的存的access_token,存储ttl为时间戳,一直在redis的缓存里面没有过期,半个月了都 ,2小时过期的

  • Tinywan 2023-11-18

    你可以提交个PR

  • 小叽叽叽叽 2023-11-19

    大佬提交,看看哪写错了,或者理解错了的麻烦指点一下,谢谢

  • Tinywan 2023-11-19

    感谢!

  • qpao123 2024-01-09

    我更新版本,插件的配置文件没有更新,只能手动复制吗

  • Tinywan 2024-01-09

    配置文件只能手动更新

qpao123

还是有问题,如果redis设置了前缀,clear方法无效,因为得到的key是带前缀的

  • 暂无评论
qpao123

不太明白,为什么要用keys方法 Redis::keys($pre . $client. ':'. $uid);
直接Redis::del() 就可以了

  • qpao123 2024-01-09

    还有一个问题,如果redis里面的key有几十万甚至更多,用Redis::keys方法会不会有性能问题,感觉这样不是很合适,希望能快点出新的版本,不太想手改vendor

  • Tinywan 2024-01-09

    欢迎提交PR

  • qpao123 2024-01-10

    其实我还没有懂,为什么要用keys获取数组,然后删除。我想的就是直接删除
    $token = Redis::keys($pre . $client. ':'. $uid);
    不这样写,直接 Redis::del($pre . $client. ':'. $uid);
    你看这样可以吗

  • Tinywan 2024-01-10

    我这边使用的场景是会存在多个客户端,会需要同时清理

Tinywan

你可以看这里

截图

  • qpao123 2024-01-10

    多客户端用keys这种命令,线上不太有好吧。或者搞个配置,是否开启多客户端。
    还有一个问题,如果redis配置了前缀,你keys获取的键名就会带有前缀,这样clear清楚不了

  • qpao123 2024-01-10

    keys这命令,是个阻塞命令,虽然一般情况问题不大,不过感觉上好像不太好。
    水平有限,个人一点愚见

  • Tinywan 2024-01-10

    我这边的实际使用场景确实是需要开启多个的

  • Tinywan 2024-01-10

    这个令牌一般都是首次登录会存储,不会有很大的并发存在

  • Tinywan 2024-01-10

    这个令牌一般都是首次登录会存储,不会有很大的并发存在

  • qpao123 2024-01-10

    不是并发问题,是keys命令阻塞,这命令执行瞬间会阻塞redis,如果redis里面的keys太多,百万级,可能对整体性能有影响

  • qpao123 2024-01-10

    然后就是redis前缀问题,设置了前缀,clear就无效

  • Tinywan 2024-01-10

    那你提个PR,直接改成del

  • qpao123 2024-01-10

    好的,稍等一下

编程小白

大佬,如何清除指定用户的token呢

  • Tinywan 2024-01-11

    暂无该方法,欢迎PR

  • 小叽叽叽叽 2024-01-12

    我是在缓存里面记录登录用户信息,和记录对应的token,每次刷新再重新写入

  • Tinywan 2024-01-12

    你想说啥子

  • 小叽叽叽叽 2024-01-15

    说他清除指定用户的token,后台强制用户退出登录状态

  • Tinywan 2024-01-15

    那直接删除缓存就行了,缓存key都是拼接的

  • 编程小白 2024-01-17

    😂可以直接去删除缓存的吧

软饭工程师

现在我有个基础平台把用户体系做好了,也是jwt 生成的access_token,我现在只需要把token解析就行了
composer 引入jwt之后,我直接

  $userinfo = \Tinywan\Jwt\JwtToken::getUser();
  var_dump($userinfo);

出现了错误

ErrorException: Undefined array key "extend" in /vendor/tinywan/jwt/src/JwtToken.php:200
Stack trace:
#0 /vendor/tinywan/jwt/src/JwtToken.php(200): support\App::{closure}(2, 'Undefined array...', '/Users/sansi/ww...', 200)
#1 /vendor/tinywan/jwt/src/JwtToken.php(77): Tinywan\Jwt\JwtToken::getTokenExtend()
#2 /vendor/tinywan/jwt/src/JwtToken.php(51): Tinywan\Jwt\JwtToken::getExtendVal('id')

请问这个怎么解决

  • Tinywan 2024-02-02

    这个是不是没配置

    'user_model' => function($uid) {
        // 返回一个数组
        return \think\facade\Db::table('resty_user')
            ->field('id,username,create_time')
            ->where('id',$uid)
            ->find();
    }
  • Tinywan 2024-02-02

    jwt 生成的access_token 代码贴一下

  • 软饭工程师 2024-02-02

    抱歉,这个问题不该问,jWT 代码别人生成的,代码我没拿到,我只需要验证token 是否有效,把加密的秘钥和token解析一下就行了,能解析成功就验证成功,是没有走数据库的

  • Tinywan 2024-02-02

    $userinfo = \Tinywan\Jwt\JwtToken::getUser();
    var_dump($userinfo); 这个配置需要走数据库,你要用她的话

  • 软饭工程师 2024-02-02

    好的,谢谢

百川

PAYLOAD 里面为什么要包两层数据
扩展数据与实践校验数据接放到同一层级
不然跟其他jwt插件验证兼容性 不好
往开发者采纳

  • Tinywan 2024-02-04

    这个能具体点吗?没听明白

年代过于久远,无法发表评论

Tinywan

13130
积分
0
获赞数
0
粉丝数
2020-01-14 加入
×
🔝