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

Tinywan

简介

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

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

认证&授权流程

截图

签名流程

  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

🚀 视频地址

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

1110 17 2
17个评论

喵了个咪

想啥来啥,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报以上错误

  • Tinywan 2022-04-09

    请使用composer官方源下载

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分钟

Tinywan

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