另类用法 hyperf/session 实现 API token

前期准备

安装 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';
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接

thanks.

讨论数量: 1

用else if 会不会更好点?而且$sessionID 有可能存在为null的情况

6天前 评论

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!