完善JWT认证逻辑

develop
fantasticbin 2 years ago
parent 6b2eb3cff8
commit 4ec5166f50

@ -25,5 +25,5 @@ class ErrorCode extends AbstractConstants
/**
* @Message("Something went wrong")
*/
public const COMMON_ERROR = 1000000;
public const COMMON_ERROR = 1200000;
}

@ -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;
}

@ -0,0 +1,11 @@
<?php
namespace App\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Phper666\JWTAuth\Middleware\JWTAuthDefaultSceneMiddleware;
#[Middleware(JWTAuthDefaultSceneMiddleware::class)]
class AuthController extends BaseController
{
}

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Controller\PunchCard\User;
use App\Controller\BaseController;
use App\Controller\AuthController;
use App\JsonRpc\PunchCardSystemExternalServiceInterface;
use App\JsonRpc\UserExternalServiceInterface;
use Hyperf\Di\Annotation\Inject;
@ -13,7 +13,7 @@ use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
#[Controller(prefix: "kq")]
class UserController extends BaseController
class UserController extends AuthController
{
/**
* 用户中心对外RPC服务

@ -2,24 +2,32 @@
declare(strict_types=1);
namespace App\Controller\PunchCard\Wechat;
namespace App\Controller\PunchCard\User;
use App\Controller\BaseController;
use App\Exception\BusinessException;
use app\Constants\Wechat\AuthErrorCode;
use App\Service\Wechat\AuthService;
use App\Service\User\WechatAuthService;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Phper666\JWTAuth\Middleware\JWTAuthDefaultSceneMiddleware;
/**
* 微信授权处理控制器
*/
#[Controller(prefix: "kq")]
class AuthController extends BaseController
class WechatAuthController extends BaseController
{
/**
* 微信授权服务
*
* @var WechatAuthService
*/
#[Inject]
protected AuthService $service;
protected WechatAuthService $service;
/**
* 通过微信授权新建用户
@ -37,4 +45,16 @@ class AuthController extends BaseController
return $this->service->codeToOpenID($code);
}
/**
* 刷新token
*
* @return array
*/
#[Middleware(JWTAuthDefaultSceneMiddleware::class)]
#[GetMapping(path: "auth/refresh_token")]
public function refreshToken() : array
{
return $this->service->refreshToken();
}
}

@ -1,17 +1,20 @@
<?php
namespace App\Service\Wechat;
namespace App\Service\User;
use App\Constants\Wechat\AuthErrorCode;
use App\Exception\BusinessException;
use App\Helper\Curl;
use App\JsonRpc\UserExternalServiceInterface;
use Hyperf\Config\Annotation\Value;
use Hyperf\Di\Annotation\Inject;
use Phper666\JWTAuth\JWT;
use Psr\SimpleCache\InvalidArgumentException;
/**
* 微信授权处理服务层
*/
class AuthService
class WechatAuthService
{
/**
* 考勤系统小程序APPID
@ -37,6 +40,14 @@ class AuthService
#[Inject]
protected UserExternalServiceInterface $userExternalService;
/**
* JWT认证组件
*
* @var JWT
*/
#[Inject]
protected JWT $jwt;
/**
* 微信通过code获取session信息请求地址
*
@ -66,6 +77,46 @@ class AuthService
throw new BusinessException($res['code'], $res['msg']);
}
return ['openid' => $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())
];
}
}

@ -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",

184
composer.lock generated

@ -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",

@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
return [
/**
* 不需要检查的路由如果使用jwt提供的默认中间件可以对某些不用做检验的路由进行配置例如登录等
* 具体的逻辑可以效仿JWT提供的默认中间件
* [
* ["GET", "/index/test"],
* ["**", "/test"]
* ]
*
* 第一个填写请求方法('**'代表支持所有的请求方法),第二个填写路由路径('/**'代表支持所有的路径)
* 如果数组中存在["**", "/**"]则默认所有的请求路由都不做jwt token的校验直接放行如果no_check_route为一个空数组
* 所有的请求路由都需要做jwt token校验
* 路由路径支持正则的写法
* 正则写法:["**", "/api/{name:.+}"] 支持模块化不做jwt token的校验例如/api/login/login
*/
'no_check_route' => [
["**", "/**"],
],
'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过期时间单位为秒
]
]
];
Loading…
Cancel
Save