{"id":19832961,"url":"https://github.com/tinywan/webman-jwt","last_synced_at":"2025-04-04T16:10:58.013Z","repository":{"id":41054089,"uuid":"461667594","full_name":"Tinywan/webman-jwt","owner":"Tinywan","description":"🔑 An authentication（认证） library that supports JSON Web Token (JWT) for webman plugin","archived":false,"fork":false,"pushed_at":"2025-03-22T09:15:10.000Z","size":82,"stargazers_count":58,"open_issues_count":12,"forks_count":24,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T17:15:06.926Z","etag":null,"topics":["jwt","jwt-authentication","jwt-token","php","php-library","tinywan","webman","workerman"],"latest_commit_sha":null,"homepage":"https://www.workerman.net/plugin/10","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tinywan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-21T01:37:33.000Z","updated_at":"2025-03-22T09:14:45.000Z","dependencies_parsed_at":"2024-06-08T12:50:35.385Z","dependency_job_id":"86a9967f-bf8e-46ff-b021-7a01e9b00045","html_url":"https://github.com/Tinywan/webman-jwt","commit_stats":{"total_commits":66,"total_committers":1,"mean_commits":66.0,"dds":0.0,"last_synced_commit":"5c8515e91ab3976277b2a8e12900dbb0d5b26053"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinywan%2Fwebman-jwt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinywan%2Fwebman-jwt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinywan%2Fwebman-jwt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinywan%2Fwebman-jwt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tinywan","download_url":"https://codeload.github.com/Tinywan/webman-jwt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208142,"owners_count":20901570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jwt","jwt-authentication","jwt-token","php","php-library","tinywan","webman","workerman"],"created_at":"2024-11-12T11:39:05.576Z","updated_at":"2025-04-04T16:10:57.984Z","avatar_url":"https://github.com/Tinywan.png","language":"PHP","readme":"# JSON Web Token (JWT) for webman plugin\n\n\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://github.com/Tinywan/webman-jwt/actions\"\u003e\n        \u003cimg src=\"https://github.com/Tinywan/webman-jwt/actions/workflows/ci.yml/badge.svg\" alt=\"Build Status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/github/Tinywan/webman-jwt\"\u003e\n        \u003cimg src=\"https://codecov.io/gh/Tinywan/webman-jwt/branch/main/graph/badge.svg\" alt=\"Codecov Status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/Tinywan/webman-jwt/releases\"\u003e\n        \u003cimg alt=\"Latest Stable Version\" src=\"https://badgen.net/packagist/v/Tinywan/webman-jwt/latest\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/Tinywan/webman-jwt/blob/main/composer.json\"\u003e\n        \u003cimg alt=\"PHP Version Require\" src=\"https://badgen.net/packagist/php/Tinywan/webman-jwt\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/Tinywan/webman-jwt/blob/main/LICENSE\"\u003e\n        \u003cimg alt=\"GitHub license\" src=\"https://badgen.net/packagist/license/Tinywan/webman-jwt\"\u003e\n    \u003c/a\u003e\n\u003c/div\u003e\n\n\nJson web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准（(RFC 7519)，该token被设计为紧凑且安全的，特别适用于分布式站点的单点登录（SSO）场景。\n\nJWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息，以便于从资源服务器获取资源，也可以增加一些额外的其它业务逻辑所必须的声明信息，该token也可直接被用于认证，也可被加密。\n\n## 认证\u0026授权流程\n\n![image](https://user-images.githubusercontent.com/14959876/159104533-f51f0a57-e085-44ab-84d7-363a4bb1eda9.png)\n\n## 签名流程\n\n1. 用户使用用户名和口令到认证服务器上请求认证。\n2. 认证服务器验证用户名和口令后，以服务器端生成JWT Token，这个token的生成过程如下：\n  \t- 认证服务器还会生成一个 Secret Key（密钥）\n \t- 对JWT Header和JWT Payload分别求Base64。在Payload可能包括了用户的抽象ID和的过期时间。\n  \t- 用密钥对JWT签名 `HMAC-SHA256(SecretKey, Base64UrlEncode(JWT-Header)+'.'+Base64UrlEncode(JWT-Payload))`\t\n3. 然后把 `base64(header).base64(payload).signature` 作为 JWT token返回客户端。\n4. 客户端使用JWT Token向应用服务器发送相关的请求。这个JWT Token就像一个临时用户权证一样。\n\n## 安装\n\n```shell\ncomposer require tinywan/jwt\n```\n\n## 使用\n\n### 生成令牌\n\n```php\nuse Tinywan\\Jwt\\JwtToken;\n\n$user = [\n    'id'  =\u003e 2022,\n    'name'  =\u003e 'Tinywan',\n    'email' =\u003e 'Tinywan@163.com'\n];\n$token = JwtToken::generateToken($user);\nvar_dump(json_encode($token));\n```\n\n**输出（json格式）**\n```json\n{\n    \"token_type\": \"Bearer\",\n    \"expires_in\": 36000,\n    \"access_token\": \"eyJ0eXAiOiJAUR-Gqtnk9LUPO8IDrLK7tjCwQZ7CI...\",\n    \"refresh_token\": \"eyJ0eXAiOiJIEGkKprvcccccQvsTJaOyNy8yweZc...\"\n}\n```\n\n**响应参数**\n\n| 参数|类型|描述|示例值|\n|:---|:---|:---|:---|\n|token_type| string |Token 类型 | Bearer |\n|expires_in| int |凭证有效时间，单位：秒 | 36000 |\n|access_token| string |访问凭证 | XXXXXXXXXXXXXXXXXXXX|\n|refresh_token| string | 刷新凭证（访问凭证过期使用 ） | XXXXXXXXXXXXXXXXXXXX|\n\n## 支持函数列表\n\n1、获取当前`id`\n```php\n$id = Tinywan\\Jwt\\JwtToken::getCurrentId();\n```\n\n2、获取所有字段\n```php\n$email = Tinywan\\Jwt\\JwtToken::getExtend();\n```\n\n3、获取自定义字段\n```php\n$email = Tinywan\\Jwt\\JwtToken::getExtendVal('email');\n```\n\n4、刷新令牌（通过刷新令牌获取访问令牌）\n```php\n$refreshToken = Tinywan\\Jwt\\JwtToken::refreshToken();\n```\n\n5、获令牌有效期剩余时长\n```php\n$exp = Tinywan\\Jwt\\JwtToken::getTokenExp();\n```\n\n6、单设备登录。默认是关闭，开启请修改配置文件`config/plugin/tinywan/jwt`\n```php\n'is_single_device' =\u003e true,\n```\n\u003e 单设备登录支持定义客户端 `client` 字段，自定义客户端单点登录（默认为`WEB`，即网页端），如：`MOBILE`、`APP`、`WECHAT`、`WEB`、`ADMIN`、`API`、`OTHER`等等\n```php\n$user = [\n    'id'  =\u003e 2022,\n    'name'  =\u003e 'Tinywan',\n    'client' =\u003e 'MOBILE',\n];\n$token = Tinywan\\Jwt\\JwtToken::generateToken($user);\nvar_dump(json_encode($token));\n```\n\n7、获取当前用户信息（模型）\n```php\n$user = Tinywan\\Jwt\\JwtToken::getUser();\n```\n该配置项目`'user_model'`为一个匿名函数，默认返回空数组，可以根据自己项目ORM定制化自己的返回模型\n\n**ThinkORM** 配置\n```php\n'user_model' =\u003e function($uid) {\n// 返回一个数组\nreturn \\think\\facade\\Db::table('resty_user')\n\t-\u003efield('id,username,create_time')\n\t-\u003ewhere('id',$uid)\n\t-\u003efind();\n}\n```\n\n**LaravelORM** 配置\n\n```php\n'user_model' =\u003e function($uid) {\n// 返回一个对象\nreturn \\support\\Db::table('resty_user')\n\t-\u003ewhere('id', $uid)\n\t-\u003eselect('id','email','mobile','create_time')\n\t-\u003efirst();\n}\n```\n\n8、令牌清理\n```php\n$res = Tinywan\\Jwt\\JwtToken::clear();\n```\n\u003e 只有配置项 `is_single_device`为`true` 才会生效。可选参数：`MOBILE`、`APP`、`WECHAT`、`WEB`、`ADMIN`、`API`、`OTHER`等等\n\n9、自定义终端`client`\n```php\n// 生成WEB令牌\n$user = [\n    'id'  =\u003e 2022,\n    'name'  =\u003e 'Tinywan',\n    'client' =\u003e JwtToken::TOKEN_CLIENT_WEB\n];\n$token = JwtToken::generateToken($user);\n\n// 生成移动端令牌\n$user = [\n    'id'  =\u003e 2022,\n    'name'  =\u003e 'Tinywan',\n    'client' =\u003e JwtToken::TOKEN_CLIENT_MOBILE\n];\n$token = JwtToken::generateToken($user);\n```\n默认是`WEB`端\n\n10、自定义访问令牌和刷新令牌过期时间\n\n```php\n$extend = [\n    'id'  =\u003e 2024,\n    'access_exp'  =\u003e 7200,  // 2 小时\n];\n$token = Tinywan\\Jwt\\JwtToken::generateToken($extend);\n```\n\n11、令牌过期错误码\n\n* 访问令牌\n  * 身份验证令牌无效：`401011`\n  * 身份验证令牌尚未生效：`401012`\n  * 身份验证会话已过期，请重新登录！：`401013`\n  * 获取的扩展字段不存在：`401014`\n  * 访问令牌未知错误：`401015`\n* 刷新令牌\n  * 刷新令牌无效：`401021`\n  * 刷新令牌尚未生效：`401022`\n  * 刷新令牌会话已过期，请再次登录！：`401023`\n  * 刷新令牌获取的扩展字段不存在：`401024`\n  * 刷新令牌未知错误：`401025`\n\n## 签名算法\n\nJWT 最常见的几种签名算法(JWA)：`HS256(HMAC-SHA256)` 、`RS256(RSA-SHA256)` 还有 `ES256(ECDSA-SHA256)`\n\n### JWT 算法列表如下\n\n```php\n+--------------+-------------------------------+--------------------+\n| \"alg\" Param  | Digital Signature or MAC      | Implementation     |\n| Value        | Algorithm                     | Requirements       |\n+--------------+-------------------------------+--------------------+\n| HS256        | HMAC using SHA-256            | Required           |\n| HS384        | HMAC using SHA-384            | Optional           |\n| HS512        | HMAC using SHA-512            | Optional           |\n| RS256        | RSASSA-PKCS1-v1_5 using       | Recommended        |\n|              | SHA-256                       |                    |\n| RS384        | RSASSA-PKCS1-v1_5 using       | Optional           |\n|              | SHA-384                       |                    |\n| RS512        | RSASSA-PKCS1-v1_5 using       | Optional           |\n|              | SHA-512                       |                    |\n| ES256        | ECDSA using P-256 and SHA-256 | Recommended+       |\n| ES384        | ECDSA using P-384 and SHA-384 | Optional           |\n| ES512        | ECDSA using P-521 and SHA-512 | Optional           |\n| PS256        | RSASSA-PSS using SHA-256 and  | Optional           |\n|              | MGF1 with SHA-256             |                    |\n| PS384        | RSASSA-PSS using SHA-384 and  | Optional           |\n|              | MGF1 with SHA-384             |                    |\n| PS512        | RSASSA-PSS using SHA-512 and  | Optional           |\n|              | MGF1 with SHA-512             |                    |\n| none         | No digital signature or MAC   | Optional           |\n|              | performed                     |                    |\n+--------------+-------------------------------+--------------------+\n\nThe use of \"+\" in the Implementation Requirements column indicates\nthat the requirement strength is likely to be increased in a future\nversion of the specification.\n```\n\u003e 可以看到被标记为 Recommended 的只有 RS256 和 ES256。\n\n### 对称加密算法\n\n\u003e 插件安装默认使用`HS256 `对称加密算法。\n\nHS256 使用同一个`「secret_key」`进行签名与验证。一旦 `secret_key `泄漏，就毫无安全性可言了。因此 HS256 只适合集中式认证，签名和验证都必须由可信方进行。\n\n### 非对称加密算法\n\n\u003e RS256 系列是使用 RSA 私钥进行签名，使用 RSA 公钥进行验证。\n\n公钥即使泄漏也毫无影响，只要确保私钥安全就行。RS256 可以将验证委托给其他应用，只要将公钥给他们就行。\n\n\u003e 以下为RS系列算法生成命令，仅供参考\n\n### RS512\n\n```php\nssh-keygen -t rsa -b 4096 -E SHA512 -m PEM -P \"\" -f RS512.key\nopenssl rsa -in RS512.key -pubout -outform PEM -out RS512.key.pub\n```\n\n### RS384\n\n```php\nssh-keygen -t rsa -b 4096 -E SHA354 -m PEM -P \"\" -f RS384.key\nopenssl rsa -in RS384.key -pubout -outform PEM -out RS384.key.pub\n```\n\n### RS256\n\n```php\nssh-keygen -t rsa -b 4096 -E SHA256 -m PEM -P \"\" -f RS256.key\nopenssl rsa -in RS256.key -pubout -outform PEM -out RS256.key.pub\n```\n\n## 🚀 视频地址\n\n\u003e 不懂的同学可以了解一下视频，会有详细的说明哦\n\n- 如何使用 JWT 认证插件：https://www.bilibili.com/video/BV1HS4y1F7Jx\n- 如何使用 JWT 认证插件（算法篇）：https://www.bilibili.com/video/BV14L4y1g7sY\n\n## 安全性\n\nhttps://www.w3cschool.cn/fastapi/fastapi-cmia3lcw.html\n\n### 概念\n\n有许多方法可以处理安全性、身份认证和授权等问题。而且这通常是一个复杂而「困难」的话题。在许多框架和系统中，仅处理安全性和身份认证就会花费大量的精力和代码（在许多情况下，可能占编写的所有代码的 50％ 或更多）。\n\nJwt 可帮助你以标准的方式轻松、快速地处理安全性，而无需研究和学习所有的安全规范。\n\n### 场景\n\n假设您在某个域中拥有后端API。并且您在另一个域或同一域的不同路径（或移动应用程序）中有一个前端。并且您希望有一种方法让前端使用用户名和密码与后端进行身份验证。我们可以使用OAuth2通过JWT来构建它。\n\n### 认证流程\n\n- 用户在前端输入`username`和`password`，然后点击Enter。\n- 前端（在用户的浏览器中运行）发送一个`username`和`password`我们的API在一个特定的URL（以申报`tokenUrl=\"token\"`）。\n- API 检查username和password，并用“令牌”响应（我们还没有实现任何这些）。“令牌”只是一个包含一些内容的字符串，我们稍后可以使用它来验证此用户。通常，令牌设置为在一段时间后过期。因此，用户稍后将不得不再次登录。如果代币被盗，风险就小了。它不像一个永久有效的密钥（在大多数情况下）。\n前端将该令牌临时存储在某处。\n- 用户单击前端以转到前端 Web 应用程序的另一部分。\n- 前端需要从 API 获取更多数据。但它需要对该特定端点进行身份验证。因此，为了使用我们的 API 进行身份验证，它会发送`Authorization`一个值为`Bearer`加上令牌的标头。如果令牌包含`foobar`，则`Authorization`标头的内容将为：`Bearer foobar`。`注意：中间是有个空格`。\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinywan%2Fwebman-jwt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftinywan%2Fwebman-jwt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinywan%2Fwebman-jwt/lists"}