From 4ec5166f50e3033baf50f7695ae6e1f26f136b6d Mon Sep 17 00:00:00 2001 From: fantasticbin Date: Thu, 17 Nov 2022 10:14:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84JWT=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Constants/ErrorCode.php | 2 +- app/Constants/Wechat/AuthErrorCode.php | 7 +- app/Controller/AuthController.php | 11 ++ .../PunchCard/User/UserController.php | 4 +- .../WechatAuthController.php} | 28 ++- .../WechatAuthService.php} | 57 +++++- composer.json | 3 +- composer.lock | 184 +++++++++++++++++- config/autoload/jwt.php | 93 +++++++++ 9 files changed, 376 insertions(+), 13 deletions(-) create mode 100644 app/Controller/AuthController.php rename app/Controller/PunchCard/{Wechat/AuthController.php => User/WechatAuthController.php} (53%) rename app/Service/{Wechat/AuthService.php => User/WechatAuthService.php} (51%) create mode 100644 config/autoload/jwt.php diff --git a/app/Constants/ErrorCode.php b/app/Constants/ErrorCode.php index 015ae77..f59d55f 100644 --- a/app/Constants/ErrorCode.php +++ b/app/Constants/ErrorCode.php @@ -25,5 +25,5 @@ class ErrorCode extends AbstractConstants /** * @Message("Something went wrong!") */ - public const COMMON_ERROR = 1000000; + public const COMMON_ERROR = 1200000; } diff --git a/app/Constants/Wechat/AuthErrorCode.php b/app/Constants/Wechat/AuthErrorCode.php index 0df037d..9455c0f 100644 --- a/app/Constants/Wechat/AuthErrorCode.php +++ b/app/Constants/Wechat/AuthErrorCode.php @@ -13,5 +13,10 @@ class AuthErrorCode extends AbstractConstants /** * @Message("请传入微信Code") */ - public const CODE_EMPTY_ERROR = 2000001; + public const CODE_EMPTY_ERROR = 1200001; + + /** + * @Message("授权失败") + */ + public const CODE_TO_AUTH_FAIL = 1200002; } \ No newline at end of file diff --git a/app/Controller/AuthController.php b/app/Controller/AuthController.php new file mode 100644 index 0000000..8f04c28 --- /dev/null +++ b/app/Controller/AuthController.php @@ -0,0 +1,11 @@ +service->codeToOpenID($code); } + + /** + * 刷新token + * + * @return array + */ + #[Middleware(JWTAuthDefaultSceneMiddleware::class)] + #[GetMapping(path: "auth/refresh_token")] + public function refreshToken() : array + { + return $this->service->refreshToken(); + } } diff --git a/app/Service/Wechat/AuthService.php b/app/Service/User/WechatAuthService.php similarity index 51% rename from app/Service/Wechat/AuthService.php rename to app/Service/User/WechatAuthService.php index 3bd2605..1c5fafc 100644 --- a/app/Service/Wechat/AuthService.php +++ b/app/Service/User/WechatAuthService.php @@ -1,17 +1,20 @@ $result['data']['openid']]; + if (empty($res['data']['user'])) { + throw new BusinessException(AuthErrorCode::CODE_TO_AUTH_FAIL); + } + + $user_data = [ + 'user_id' => $res['data']['user']['user_id'], + 'nickname' => $res['data']['user']['user_nickname'], + 'openid' => $res['data']['user']['user_openid'] + ]; + + try { + $token = $this->jwt->getToken('default', $user_data); + } catch (InvalidArgumentException) { + // TODO 记录日志 + throw new BusinessException(AuthErrorCode::CODE_TO_AUTH_FAIL); + } + + return [ + 'token' => $token->toString(), + 'exp' => $this->jwt->getTTL($token->toString()) + ]; + } + + /** + * 刷新token + * + * @return array + */ + public function refreshToken() : array + { + try { + $token = $this->jwt->refreshToken(); + } catch (InvalidArgumentException) { + // TODO 记录日志 + throw new BusinessException(AuthErrorCode::CODE_TO_AUTH_FAIL); + } + + return [ + 'token' => $token->toString(), + 'exp' => $this->jwt->getTTL($token->toString()) + ]; } } \ No newline at end of file diff --git a/composer.json b/composer.json index c173c71..3cb3b87 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,8 @@ "hyperf/rpc-client": "~2.2.0", "hyperf/rpc-server": "~2.2.0", "hyperf/service-governance-consul": "~2.2.0", - "hyperf/validation": "^2.2" + "hyperf/validation": "^2.2", + "phper666/jwt-auth": "~4.0.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.0", diff --git a/composer.lock b/composer.lock index 86116f6..847f76a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7cc40bd39d6d590a4e06bfb1d56c0abb", + "content-hash": "7f8915491bc01099466689096453ac63", "packages": [ { "name": "doctrine/annotations", @@ -2515,6 +2515,101 @@ ], "time": "2022-10-10T19:10:24+00:00" }, + { + "name": "lcobucci/clock", + "version": "2.2.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/lcobucci/clock/2.2.0/lcobucci-clock-2.2.0.zip", + "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3", + "shasum": "" + }, + "require": { + "php": "^8.0", + "stella-maris/clock": "^0.1.4" + }, + "require-dev": { + "infection/infection": "^0.26", + "lcobucci/coding-standard": "^8.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\Clock\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com" + } + ], + "description": "Yet another clock abstraction", + "time": "2022-04-19T19:34:17+00:00" + }, + { + "name": "lcobucci/jwt", + "version": "4.1.5", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/lcobucci/jwt/4.1.5/lcobucci-jwt-4.1.5.zip", + "reference": "fe2d89f2eaa7087af4aa166c6f480ef04e000582", + "shasum": "" + }, + "require": { + "ext-hash": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-sodium": "*", + "lcobucci/clock": "^2.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "infection/infection": "^0.21", + "lcobucci/coding-standard": "^6.0", + "mikey179/vfsstream": "^1.6.7", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/php-invoker": "^3.1", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "time": "2021-09-28T19:34:56+00:00" + }, { "name": "markrogoyski/math-php", "version": "v2.6.0", @@ -3020,6 +3115,56 @@ ], "time": "2020-10-12T12:39:22+00:00" }, + { + "name": "phper666/jwt-auth", + "version": "v4.0.7", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phper666/jwt-auth/v4.0.7/phper666-jwt-auth-v4.0.7.zip", + "reference": "c42e1ef968d300e7e74e449e5e93cda7d22de33f", + "shasum": "" + }, + "require": { + "ext-swoole": ">=4.4", + "lcobucci/jwt": "4.1.5", + "nesbot/carbon": "^1.0 || ^2.0", + "php": ">=7.4" + }, + "suggest": { + "hyperf/cache": "required hyperf/cache ~2.2.0", + "hyperf/command": "required hyperf/command ~2.2.0", + "hyperf/config": "required hyperf/config ~2.2.0", + "hyperf/di": "required hyperf/di ~2.2.0" + }, + "type": "library", + "extra": { + "hyperf": { + "config": "Phper666\\JWTAuth\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Phper666\\JWTAuth\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Li Yuzhao", + "email": "562405704@qq.com", + "homepage": "https://github.com/phper666/jwt-auth", + "role": "Developer" + } + ], + "description": "jwt-auth Component", + "keywords": [ + "hyperf", + "php" + ], + "time": "2022-04-19T11:54:50+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.0", @@ -3628,6 +3773,43 @@ "description": "A polyfill for getallheaders.", "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "stella-maris/clock", + "version": "0.1.6", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/stella-maris/clock/0.1.6/stella-maris-clock-0.1.6.zip", + "reference": "a94228dac03c9a8411198ce8c8dacbbe99c930c3", + "shasum": "" + }, + "require": { + "php": "^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "StellaMaris\\Clock\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Heigl", + "role": "Maintainer" + } + ], + "description": "A pre-release of the proposed PSR-20 Clock-Interface", + "homepage": "https://gitlab.com/stella-maris/clock", + "keywords": [ + "clock", + "datetime", + "point in time", + "psr20" + ], + "time": "2022-09-27T15:03:11+00:00" + }, { "name": "symfony/console", "version": "v5.4.11", diff --git a/config/autoload/jwt.php b/config/autoload/jwt.php new file mode 100644 index 0000000..eb21313 --- /dev/null +++ b/config/autoload/jwt.php @@ -0,0 +1,93 @@ + [ + ["**", "/**"], + ], + + 'login_type' => env('JWT_LOGIN_TYPE', 'mpop'), // 登录方式,sso为单点登录,同一个用户只能登录一个端,mpop为多点登录 + + /** + * 单点登录自定义数据中必须存在uid的键值,这个key你可以自行定义,只要自定义数据中存在该键即可 + */ + 'sso_key' => 'user_id', + + /** + * 只能用于Hmac包下的加密非对称算法,其它的都会使用公私钥 + */ + 'secret' => env('JWT_SECRET', 'juzhongGroup'), + + /** + * JWT 权限keys + * 对称算法: HS256, HS384 & HS512 使用 `JWT_SECRET`. + * 非对称算法: RS256, RS384 & RS512 / ES256, ES384 & ES512 使用下面的公钥私钥,需要自己去生成. + */ + 'keys' => [ + 'public' => env('JWT_PUBLIC_KEY'), // 公钥,例如:'file:///path/to/public/key' + 'private' => env('JWT_PRIVATE_KEY'), // 私钥,例如:'file:///path/to/private/key' + + /** + * 你的私钥的密码。不需要密码可以不用设置 + */ + 'passphrase' => env('JWT_PASSPHRASE'), + ], + + 'ttl' => env('JWT_TTL', 7200), // token过期时间,单位为秒 + + /** + * 支持的对称算法:HS256、HS384、HS512 + * 支持的非对称算法:RS256、RS384、RS512、ES256、ES384、ES512 + */ + 'alg' => env('JWT_ALG', 'HS256'), // jwt的hearder加密算法 + + /** + * jwt使用到的缓存前缀 + * 建议使用独立的redis做缓存,这样比较好做分布式 + */ + 'cache_prefix' => 'juzhong:jwt', + + /** + * 是否开启黑名单,单点登录和多点登录的注销、刷新使原token失效,必须要开启黑名单,目前黑名单缓存只支持hyperf缓存驱动 + */ + 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), + + /** + * 黑名单的宽限时间 单位为:秒,注意:如果使用单点登录,该宽限时间无效 + */ + 'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0), + + /** + * 签发者 + */ + 'issued_by' => 'phper666/jwt', + + /** + * 区分不同场景的token,比如你一个项目可能会有多种类型的应用接口鉴权,下面自行定义,我只是举例子 + * 下面的配置会自动覆盖根配置,比如application1会里面的数据会覆盖掉根数据 + * 下面的scene会和根数据合并 + * scene必须存在一个default + * 什么叫根数据,这个配置的一维数组,除了scene都叫根配置 + */ + 'scene' => [ + 'default' => [ + 'secret' => 'juzhongGroup', // 非对称加密使用字符串,请使用自己加密的字符串 + 'login_type' => 'mpop', // 登录方式,sso为单点登录,mpop为多点登录 + 'ttl' => 7200, // token过期时间,单位为秒 + ] + ] +];