优化代码

main
gzydong 2021-05-23 16:52:01 +08:00
parent ddae0895a3
commit 60ea1688b7
13 changed files with 156 additions and 221 deletions

View File

@ -46,7 +46,7 @@ class ChatMessageProducer extends ProducerMessage
public function __construct(string $event, array $data, array $options = [])
{
$message = [
'uuid' => uniqid(),
'uuid' => uniqid((strval(mt_rand(0, 1000)))),
'event' => $event,
'data' => $data,
'options' => $options

View File

@ -13,12 +13,9 @@ namespace App\Controller\Api\V1;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use App\Middleware\JWTAuthMiddleware;
use App\Model\User;
use App\Service\UserService;
use App\Service\SmsCodeService;
use Phper666\JWTAuth\JWT;
/**
* 授权相关控制器
@ -38,12 +35,6 @@ class AuthController extends CController
*/
private $smsCodeService;
/**
* @Inject
* @var JWT
*/
protected $jwt;
/**
* 授权登录接口
* @RequestMapping(path="login", methods="post")
@ -63,10 +54,7 @@ class AuthController extends CController
}
try {
$token = $this->jwt->getToken([
'user_id' => $userInfo['id'],
'platform' => $params['platform'],
]);
$token = auth('jwt')->login($userInfo);
} catch (\Exception $exception) {
return $this->response->error('登录异常,请稍后再试!');
}
@ -74,14 +62,14 @@ class AuthController extends CController
return $this->response->success([
'authorize' => [
'access_token' => $token,
'expires_in' => $this->jwt->getTTL()
'expires_in' => auth('jwt')->getJwtManager()->getTtl()
],
'user_info' => [
'nickname' => $userInfo['nickname'],
'avatar' => $userInfo['avatar'],
'gender' => $userInfo['gender'],
'motto' => $userInfo['motto'],
'email' => $userInfo['email'],
'nickname' => $userInfo->nickname,
'avatar' => $userInfo->avatar,
'gender' => $userInfo->gender,
'motto' => $userInfo->motto,
'email' => $userInfo->email,
]
]);
}
@ -89,11 +77,10 @@ class AuthController extends CController
/**
* 退出登录接口
* @RequestMapping(path="logout", methods="post")
* @Middleware(JWTAuthMiddleware::class)
*/
public function logout()
{
$this->jwt->logout();
auth('jwt')->check() && auth('jwt')->logout();
return $this->response->success([], 'Successfully logged out');
}
@ -164,14 +151,17 @@ class AuthController extends CController
/**
* 授权刷新接口
* @RequestMapping(path="refresh", methods="post")
* @Middleware(JWTAuthMiddleware::class)
*/
public function refresh()
{
if (auth('jwt')->guest()) {
return $this->response->fail('登录 token 刷新失败!');
}
return $this->response->success([
'authorize' => [
'token' => $this->jwt->refreshToken(),
'expire' => $this->jwt->getTTL()
'token' => auth('jwt')->refresh(),
'expire' => auth('jwt')->getJwtManager()->getTtl()
]
]);
}

View File

@ -34,6 +34,8 @@ class CController extends AbstractController
*/
public function uid()
{
return $this->request->getAttribute('auth_data')['user_id'] ?? 0;
$guard = auth('jwt');
return $guard->check() ? $guard->user()->getId() : 0;
}
}

View File

@ -21,7 +21,6 @@ use Swoole\Http\Request;
use Swoole\Websocket\Frame;
use Swoole\Http\Response;
use Swoole\WebSocket\Server;
use Phper666\JWTAuth\JWT;
use App\Service\SocketClientService;
use App\Service\MessageHandleService;
use App\Model\Group\GroupMember;
@ -34,12 +33,6 @@ use App\Amqp\Producer\ChatMessageProducer;
*/
class WebSocketController implements OnMessageInterface, OnOpenInterface, OnCloseInterface
{
/**
* @Inject
* @var JWT
*/
private $jwt;
/**
* @inject
* @var SocketClientService
@ -68,14 +61,13 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos
*/
public function onOpen($server, Request $request): void
{
$token = $request->get['token'] ?? '';
$userInfo = $this->jwt->getParserData($token);
$userInfo['user_id'] = intval($userInfo['user_id']);
// 当前连接的用户
$user_id = auth('jwt')->user()->getId();
stdout_log()->notice("用户连接信息 : user_id:{$userInfo['user_id']} | fd:{$request->fd} 时间:" . date('Y-m-d H:i:s'));
stdout_log()->notice("用户连接信息 : user_id:{$user_id} | fd:{$request->fd} 时间:" . date('Y-m-d H:i:s'));
// 判断是否存在异地登录
$isOnline = $this->socketClientService->isOnlineAll($userInfo['user_id']);
$isOnline = $this->socketClientService->isOnlineAll($user_id);
// 若开启单点登录,则主动关闭之前登录的连接
if ($isOnline) {
@ -83,18 +75,18 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos
}
// 绑定fd与用户关系
$this->socketClientService->bindRelation($request->fd, $userInfo['user_id']);
$this->socketClientService->bindRelation($request->fd, $user_id);
// 加入群聊
$groupIds = GroupMember::getUserGroupIds($userInfo['user_id']);
$groupIds = GroupMember::getUserGroupIds($user_id);
foreach ($groupIds as $group_id) {
SocketRoom::getInstance()->addRoomMember(strval($group_id), strval($userInfo['user_id']));
SocketRoom::getInstance()->addRoomMember(strval($group_id), strval($user_id));
}
if (!$isOnline) {
// 推送消息至队列
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_ONLINE_STATUS, [
'user_id' => $userInfo['user_id'],
'user_id' => $user_id,
'status' => 1,
'notify' => '好友上线通知...'
]));

View File

@ -24,7 +24,6 @@ class CorsMiddleware implements MiddlewareInterface
$response = Context::get(ResponseInterface::class);
$response = $response->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Credentials', 'true')
// Headers 可以根据实际情况进行改写。
->withHeader('Access-Control-Allow-Headers', 'DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization');
Context::set(ResponseInterface::class, $response);

View File

@ -16,9 +16,6 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Phper666\JWTAuth\JWT;
use Phper666\JWTAuth\Util\JWTUtil;
use Hyperf\Utils\Context;
/**
* Http Token 授权验证中间件
@ -37,60 +34,21 @@ class JWTAuthMiddleware implements MiddlewareInterface
*/
protected $response;
/**
* @var JWT
*/
protected $jwt;
public function __construct(HttpResponse $response, RequestInterface $request, JWT $jwt)
public function __construct(HttpResponse $response, RequestInterface $request)
{
$this->response = $response;
$this->request = $request;
$this->jwt = $jwt;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$isValidToken = false;
// 获取请求token
$token = $request->getHeaderLine('Authorization');
if (empty($token)) {
$token = $this->request->input('token', '');
} else {
$token = JWTUtil::handleToken($token);
}
if (!empty($token)) {
try {
if ($token !== false && $this->jwt->checkToken($token)) {
$isValidToken = true;
}
} catch (\Exception $e) {
}
}
if (!$isValidToken) {
if (auth('jwt')->guest()) {
return $this->response->withStatus(401)->json([
'code' => 401,
'message' => 'Token authentication does not pass',
'message' => 'Token authentication does not pass !',
]);
}
$request = $this->setRequestContext($token);
return $handler->handle($request);
}
private function setRequestContext(string $token): ServerRequestInterface
{
$request = Context::get(ServerRequestInterface::class);
$jwtData = $this->jwt->getParserData($token);
$request = $request->withAttribute('auth_data', $jwtData);
Context::set(ServerRequestInterface::class, $request);
return $request;
}
}

View File

@ -11,7 +11,6 @@ declare(strict_types=1);
namespace App\Middleware;
use Phper666\JWTAuth\JWT;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
@ -31,12 +30,6 @@ class WebSocketAuthMiddleware implements MiddlewareInterface
*/
protected $container;
/**
* @inject
* @var JWT
*/
private $jwt;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
@ -45,11 +38,7 @@ class WebSocketAuthMiddleware implements MiddlewareInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// 授权验证拦截握手请求并实现权限检查
$token = $request->getQueryParams()['token'] ?? '';
try {
$this->jwt->checkToken($token);
} catch (\Exception $e) {
if (auth('jwt')->guest()) {
return $this->container->get(\Hyperf\HttpServer\Contract\ResponseInterface::class)->raw('Forbidden');
}

View File

@ -4,6 +4,9 @@ declare (strict_types=1);
namespace App\Model;
use Qbhy\HyperfAuth\AuthAbility;
use Qbhy\HyperfAuth\Authenticatable;
/**
* Class User
*
@ -18,8 +21,10 @@ namespace App\Model;
* @property integer $created_at 注册时间
* @package App\Model
*/
class User extends BaseModel
class User extends BaseModel implements Authenticatable
{
use AuthAbility;
protected $table = 'users';
protected $fillable = [
@ -34,4 +39,8 @@ class User extends BaseModel
];
protected $casts = [];
protected $hidden = [
'password'
];
}

View File

@ -28,7 +28,7 @@ class UserService extends BaseService
*
* @param string $mobile 手机号
* @param string $password 登录密码
* @return array|bool
* @return User|bool
*/
public function login(string $mobile, string $password)
{
@ -40,7 +40,7 @@ class UserService extends BaseService
return false;
}
return $user->toArray();
return $user;
}
/**

View File

@ -31,13 +31,13 @@
"hyperf/websocket-server": "^2.0",
"hyperf/constants": "^2.0",
"hyperf/validation": "^2.0",
"phper666/jwt-auth": "^3.0",
"hyperf/filesystem": "^2.0",
"hashids/hashids": "^4.0",
"ext-json": "*",
"hyperf/view": "^2.0",
"hyperf/view-engine": "^2.0",
"phpmailer/phpmailer": "^6.2"
"phpmailer/phpmailer": "^6.2",
"96qbhy/hyperf-auth": "^2.3"
},
"require-dev": {
"swoole/ide-helper": "^4.5",

111
config/autoload/auth.php Normal file
View File

@ -0,0 +1,111 @@
<?php
declare(strict_types=1);
/**
* This file is part of qbhy/hyperf-auth.
*
* @link https://github.com/qbhy/hyperf-auth
* @document https://github.com/qbhy/hyperf-auth/blob/master/README.md
* @contact qbhy0715@qq.com
* @license https://github.com/qbhy/hyperf-auth/blob/master/LICENSE
*/
use Qbhy\SimpleJwt\Encoders;
use Qbhy\SimpleJwt\EncryptAdapters as Encrypter;
/*
* This file is part of qbhy/hyperf-auth.
*
* @link https://github.com/qbhy/hyperf-auth
* @document https://github.com/qbhy/hyperf-auth/blob/master/README.md
* @contact qbhy0715@qq.com
* @license https://github.com/qbhy/hyperf-auth/blob/master/LICENSE
*/
return [
'default' => [
'guard' => 'jwt',
'provider' => 'users',
],
'guards' => [
'jwt' => [
'driver' => Qbhy\HyperfAuth\Guard\JwtGuard::class,
'provider' => 'users',
/*
* 以下是 simple-jwt 配置
* 必填
* jwt 服务端身份标识
*/
'secret' => env('SIMPLE_JWT_SECRET'),
/*
* 可选配置
* jwt 默认头部token使用的字段
*/
'header_name' => env('JWT_HEADER_NAME', 'Authorization'),
/*
* 可选配置
* jwt 生命周期,单位分钟
*/
'ttl' => (int)env('SIMPLE_JWT_TTL', 60 * 60),
/*
* 可选配置
* 允许过期多久以内的 token 进行刷新
*/
'refresh_ttl' => (int)env('SIMPLE_JWT_REFRESH_TTL', 60 * 60 * 24 * 7),
/*
* 可选配置
* 默认使用的加密类
*/
'default' => Encrypter\PasswordHashEncrypter::class,
/*
* 可选配置
* 加密类必须实现 Qbhy\SimpleJwt\Interfaces\Encrypter 接口
*/
'drivers' => [
Encrypter\PasswordHashEncrypter::alg() => Encrypter\PasswordHashEncrypter::class,
Encrypter\CryptEncrypter::alg() => Encrypter\CryptEncrypter::class,
Encrypter\SHA1Encrypter::alg() => Encrypter\SHA1Encrypter::class,
Encrypter\Md5Encrypter::alg() => Encrypter\Md5Encrypter::class,
],
/*
* 可选配置
* 编码类
*/
'encoder' => new Encoders\Base64UrlSafeEncoder(),
// 'encoder' => new Encoders\Base64Encoder(),
/*
* 可选配置
* 缓存类
*/
//'cache' => new \Doctrine\Common\Cache\FilesystemCache(sys_get_temp_dir()),
// 如果需要分布式部署,请选择 redis 或者其他支持分布式的缓存驱动
'cache' => function () {
return make(\Qbhy\HyperfAuth\HyperfRedisCache::class);
},
/*
* 可选配置
* 缓存前缀
*/
'prefix' => env('SIMPLE_JWT_PREFIX', 'default'),
],
'session' => [
'driver' => Qbhy\HyperfAuth\Guard\SessionGuard::class,
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => \Qbhy\HyperfAuth\Provider\EloquentProvider::class,
'model' => App\Model\User::class, // 需要实现 Qbhy\HyperfAuth\Authenticatable 接口
],
],
];

View File

@ -1,115 +0,0 @@
<?php
declare(strict_types=1);
return [
'login_type' => env('JWT_LOGIN_TYPE', 'mpop'), // 登录方式sso为单点登录mpop为多点登录
/**
* 单点登录自定义数据中必须存在uid的键值这个key你可以自行定义只要自定义数据中存在该键即可
*/
'sso_key' => 'uid',
'secret' => env('JWT_SECRET', 'phper666'), // 非对称加密使用字符串,请使用自己加密的字符串
/**
* 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'
],
'ttl' => env('JWT_TTL', 7200), // token过期时间单位为秒
'alg' => env('JWT_ALG', 'HS256'), // jwt的hearder加密算法
/**
* 支持的算法
*/
'supported_algs' => [
'HS256' => 'Lcobucci\JWT\Signer\Hmac\Sha256',
'HS384' => 'Lcobucci\JWT\Signer\Hmac\Sha384',
'HS512' => 'Lcobucci\JWT\Signer\Hmac\Sha512',
'ES256' => 'Lcobucci\JWT\Signer\Ecdsa\Sha256',
'ES384' => 'Lcobucci\JWT\Signer\Ecdsa\Sha384',
'ES512' => 'Lcobucci\JWT\Signer\Ecdsa\Sha512',
'RS256' => 'Lcobucci\JWT\Signer\Rsa\Sha256',
'RS384' => 'Lcobucci\JWT\Signer\Rsa\Sha384',
'RS512' => 'Lcobucci\JWT\Signer\Rsa\Sha512',
],
/**
* 对称算法名称
*/
'symmetry_algs' => [
'HS256',
'HS384',
'HS512'
],
/**
* 非对称算法名称
*/
'asymmetric_algs' => [
'RS256',
'RS384',
'RS512',
'ES256',
'ES384',
'ES512',
],
/**
* 是否开启黑名单单点登录和多点登录的注销、刷新使原token失效必须要开启黑名单目前黑名单缓存只支持hyperf缓存驱动
*/
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
/**
* 黑名单的宽限时间 单位为:秒,注意:如果使用单点登录,该宽限时间无效
*/
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),
/**
* 黑名单缓存token时间注意该时间一定要设置比token过期时间要大一点默认为1天,最好设置跟过期时间一样
*/
'blacklist_cache_ttl' => env('JWT_TTL', 86400),
'blacklist_prefix' => 'phper666_jwt', // 黑名单缓存的前缀
/**
* 区分不同场景的token比如你一个项目可能会有多种类型的应用接口鉴权,下面自行定义,我只是举例子
* 下面的配置会自动覆盖根配置比如application1会里面的数据会覆盖掉根数据
* 下面的scene会和根数据合并
* scene必须存在一个default
* 什么叫根数据这个配置的一维数组除了scene都叫根配置
*/
'scene' => [
'default' => [],
'application1' => [
'secret' => 'application1', // 非对称加密使用字符串,请使用自己加密的字符串
'login_type' => 'sso', // 登录方式sso为单点登录mpop为多点登录
'sso_key' => 'uid',
'ttl' => 7200, // token过期时间单位为秒
'blacklist_cache_ttl' => env('JWT_TTL', 7200), // 黑名单缓存token时间注意该时间一定要设置比token过期时间要大一点默认为100秒,最好设置跟过期时间一样
],
'application2' => [
'secret' => 'application2', // 非对称加密使用字符串,请使用自己加密的字符串
'login_type' => 'sso', // 登录方式sso为单点登录mpop为多点登录
'sso_key' => 'uid',
'ttl' => 7200, // token过期时间单位为秒
'blacklist_cache_ttl' => env('JWT_TTL', 7200), // 黑名单缓存token时间注意该时间一定要设置比token过期时间要大一点默认为100秒,最好设置跟过期时间一样
],
'application3' => [
'secret' => 'application3', // 非对称加密使用字符串,请使用自己加密的字符串
'login_type' => 'mppo', // 登录方式sso为单点登录mpop为多点登录
'ttl' => 7200, // token过期时间单位为秒
'blacklist_cache_ttl' => env('JWT_TTL', 7200), // 黑名单缓存token时间注意该时间一定要设置比token过期时间要大一点默认为100秒,最好设置跟过期时间一样
]
],
'model' => [ // TODO 支持直接获取某模型的数据
'class' => '',
'pk' => 'uid'
]
];

View File

@ -48,7 +48,7 @@ return [
],
'settings' => [
'enable_coroutine' => true,
'worker_num' => swoole_cpu_num(),
'worker_num' => 1,
'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
'open_tcp_nodelay' => true,
'max_coroutine' => 100000,