Hyperf中间件验证用户登录状态
才开始接触hyperf,就被他惊人的并发处理性能所惊呆了。所以在工作空余之时学习一下hyperf。
今天要学习一下hyperf的中间件的使用。
新建一个中间件,主要功能就是取每次请求的header头里面的uid和token来比对用户是否是正确的登录用户
<?php
declare(strict_types=1);
namespace App\Middleware;
use App\Common\Tools;
use App\Model\User\UserModel;
use Hyperf\Utils\Context;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class CheckLoginMiddleware implements MiddlewareInterface
{
use Tools;
/**
* @var ContainerInterface
*/
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$uid = $request->getHeader('uid');
$token = $request->getHeader('token');
if (isset($uid) and isset($token) and isset($uid[0]) and isset($token[0])) {
$user = UserModel::findFromCache($uid[0]);
if (!isset($user))
return $this->error('没有找到该用户', 999);
$user_token = md5($user['token'] . env('APP_KEY'));
if ($user_token === $token[0]) {
$request = $request->withAttribute("user", $user);
Context::set(ServerRequestInterface::class, $request);
return $handler->handle($request);
} else {
return $this->error('登录错误', 999);
}
}
return $this->error('登录参数错误', 999);
}
}
如果验证通过了,那么把当前的userModel取到的用户模型通过withAttribute方法挂载到request中并传递给后面的controller使用。
这里有一个上下文存储的代码
Context::set(ServerRequestInterface::class, $request);
在群里争论了很久,加不加这一句又没有影响,有人说没事不用加,框架自动自动协程化了,多个用户并发请求并不会造成代码共用,内存穿透之类的错误,
但是又有人说必须要加,在高并发下会出现甲用户取到乙用户的数据,纠结了很久,查了文档,写得也比较模糊,但是百度了一下,看了看别人写的中间件,貌似都加了,算了,加上吧。
至于好大的并发出出现内容混淆也没测试,加上总之不为过吧,如果官方文档能解释一下就更好了。。
然后就是在我们的路由中使用这个中间件了。
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
use Hyperf\HttpServer\Router\Router;
Router::get('/favicon.ico', function () {
return '';
});
Router::addRoute(['GET', 'POST', 'HEAD'], '/', 'App\Controller\IndexController@index');
Router::addGroup(
'/v1', function () {
Router::addRoute(['GET', 'POST'], '/index/home', 'App\Controller\IndexController@home');
Router::addRoute(['GET', 'POST'], '/map/get_map', 'App\Controller\MapController@get_map');
},
['middleware' => [\App\Middleware\CheckLoginMiddleware::class]]
);
至此我们的中间件就可以正常工作了,然后再后面的controller中去取user的取法
$user = $this->request->getAttribute('user');
这样就直接取到了
