前期準備
安裝 hyperf/session 使用 redis 作為 session 儲存
我的做法
把session的id作為 api key,這樣登入的時候只要把資訊寫入session,前端傳遞id key 進來 就可以調取session裡的資訊,並且只要把id傳遞到其他客戶端只要相同key也可以調取資訊,只要redis裡的資訊沒有過期
一開始遇到的問題
session預設方法是從cookie裡拿,有點不方便,前端需要注意 cors 跨域問題然後還要傳遞cookie。
解決方法
使用 切面切入 Hyperf\Session\SessionManager::parseSessionId 獲取id的方法,魔改本方法
以下是我的程式碼
<?php
declare(strict_types=1);
namespace App\Aspect;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Aspect;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Redis\RedisFactory;
use Hyperf\Utils\Str;
use Psr\Container\ContainerInterface;
use Hyperf\Di\Aop\ProceedingJoinPoint;
/**
* @Aspect
*/
class SessionAspect extends AbstractAspect
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @Inject()
* @var RequestInterface
*/
protected $request;
/**
* @Inject()
* @var ConfigInterface
*/
protected $config;
/**
* @Inject()
* @var StdoutLoggerInterface
*/
protected $logger;
/**
* @var array
*/
public $classes = [
'Hyperf\Session\SessionManager::parseSessionId'
];
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function process(ProceedingJoinPoint $proceedingJoinPoint)
{
$priority = $this->config->get('session.options.id_priority');
$sessionID = null;
// 預設從 cookie 裡獲取 ID
if ($priority['cookie']) {
$cookies = $this->request->getCookieParams();
foreach ($cookies as $key => $value) {
if ($key === $this->getSessionName()) {
$sessionID = (string)$value;
}
}
}
// header 獲取id
if (isset($priority['header'])) {
if ($this->request->hasHeader($priority['header'])) {
$sessionID = (string)$this->request->getHeader($priority['header'])[0];
}
}
// url 引數 獲取id
if (isset($priority['get']) && $sessionID === null) {
$params = $this->request->getQueryParams();
if ($params && array_key_exists($priority['get'], $params)) {
$sessionID = (string)$params[$priority['get']];
}
}
if ($sessionID && strlen($sessionID) === 40) {
$redis = $this->container->get(RedisFactory::class)->get('session');
$existsKey = $redis->exists($sessionID);
if ($existsKey !== 1) {
return Str::random(40);
}
}
$this->logger->notice('獲取到 ' . microtime(true) . "\t" . 'Session => ' . $sessionID);
return $sessionID;
}
public function getSessionName(): string
{
return 'HYPERF_SESSION_ID';
}
}