【问题标题】:migrating oAuth from controller to middleware slim将 oAuth 从控制器迁移到中间件 slim
【发布时间】:2018-08-09 19:31:42
【问题描述】:

我正在使用This 库来实现一个带有 Oauth 的 API,我想在某些路由中添加中间件,但我希望 ouath 在其他中间件之前运行,所以如果我错了,请纠正我,但方法要做到这一点是通过使 oAuth 成为中间件而不是控制器的一部分。

实际的设置是这样的。

依赖文件是这样的

$container['oAuth'] = function ($c) {

    $storage = new App\DataAccess\_oAuth2_CustomStorage($c->get('pdo'));

    // Pass a storage object or array of storage objects to the OAuth2 server class
    $server = new OAuth2\Server($storage);

    // add grant types
    $server->addGrantType(new OAuth2\GrantType\UserCredentials($storage));
    $server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage));
    $server->addGrantType(new OAuth2\GrantType\RefreshToken($storage));

    return $server;
};
$container['App\Controllers\_Controller_oAuth2'] = function ($c) {
    return new _Controller_oAuth2($c->get('logger'), $c->get('App\DataAccess\_DataAccess'), $c->get('oAuth'));
};

而实际的控制器是这样的:

public function __construct(LoggerInterface $logger, _DataAccess $dataaccess, $server)
    {
        parent::__construct($logger,$dataaccess);
        $this->oAuth2server = $server;
    }

     /**
     * @param \Psr\Http\Message\ServerRequestInterface $request
     * @param \Psr\Http\Message\ResponseInterface      $response
     * @param array                                    $next
     *
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function validateToken($request)
    {
        $this->logger->info(substr(strrchr(rtrim(__CLASS__, '\\'), '\\'), 1).': '.__FUNCTION__);

        // convert a request from PSR7 to hhtpFoundation
        $httpFoundationFactory = new HttpFoundationFactory();
        $symfonyRequest = $httpFoundationFactory->createRequest($request);
        $bridgeRequest = BridgeRequest::createFromRequest($symfonyRequest);
        $token = $this->oAuth2server->getAccessTokenData($bridgeRequest);

        if (!$this->oAuth2server->verifyResourceRequest($bridgeRequest)) {
            $this->oAuth2server->getResponse()->send();
            die;
         }

        // store the user_id
        $token = $this->oAuth2server->getAccessTokenData($bridgeRequest);
        $this->user = $token['user_id'];

        return TRUE;
    }

    // needs an oAuth2 Client credentials grant
    // with Resource owner credentials grant alseo works
    public function getAll(Request $request, Response $response, $args) {
        if ($this->validateToken($request)) {
            parent::getAll($request, $response, $args);

        }           
    }

现在,我尝试在我的中间件文件上创建我的函数以将其添加到所需的路由中,它看起来像这样:

$oathMiddleWare = function ($request,$response,$next){

    $container = $this->$app->getContainer();
    $responsen = $response->withHeader('Content-Type', 'application/json');

    $this->oAuth2server = $container->get('oAuth');

    $httpFoundationFactory = new HttpFoundationFactory();
        $symfonyRequest = $httpFoundationFactory->createRequest($request);
        $bridgeRequest = BridgeRequest::createFromRequest($symfonyRequest);
        $token = $this->oAuth2server->getAccessTokenData($bridgeRequest);

        if (!$this->oAuth2server->verifyResourceRequest($bridgeRequest)) {
            $this->oAuth2server->getResponse()->send();
            $responsen = $responsen ->withStatus(400);
            return $responsen;
         }

        // store the user_id
        $token = $this->oAuth2server->getAccessTokenData($bridgeRequest);
        $this->user = $token['user_id'];
        $next($request,$responsen);
        return $responsen;

};

我第一次尝试$container = $app->getContainer();,但它给了我一个错误说Call to a member function getContainer() on null

现在使用我刚刚分享的代码,我收到一个错误Type: Slim\Exception\ContainerValueNotFoundException Message: Identifier “” is not defined.

对完成这项工作有什么建议吗?

【问题讨论】:

  • 您设法解决了这个问题吗?我相信您应该将中间件中的容器引用为$this->getContainer()

标签: php slim middleware slim-3


【解决方案1】:

要访问中间件中的容器,您可以执行以下操作:

1/ 在特定的文件和类中创建你的中间件

<?php
namespace api\middlewares;

class SecurityMiddleware
{
    public function __invoke($request, $response, $next)
    {
        // do your thing
        $response = $next($request, $response);

        return $response;
    }
}

2/ 使用这个类的构造函数来设置容器并在你的中间件中访问它

private $container;

public function __construct($container)
{
    $this->container = $container;
}

3/ 像这样添加中间件

// security check
$app->add(new \api\middlewares\SecurityMiddleware($app->getContainer()));

我基于另一个 api 框架制作了一个 Slim 3 API 框架,我在其中使用了这种技术和 oAuth2 身份验证,并在每个控制器内部定义了路由安全性。你可以去看看能不能帮到你:https://github.com/mickaeleuranie/slim-api(有时间我会加JWT和call ratio)

我所做的是通过定义一个受 Yii 框架启发的数组来定义每个控制器的访问权限,如下所示:

public function accessRules()
{
    return [
        [
            'allow' => true,
            'actions' => [
                'edit',
            ],
            'roles' => ['@'],
        ],
        [
            'allow' => true,
            'actions' => [
                'get',
            ],
            'roles' => ['@'],
            'scopes' => 'admin',
        ],
        [
            'allow' => true,
            'actions' => [
                'login',
                'sociallogin',
                'signup',
                'contact',
            ],
            'roles' => ['?'],
        ],
    ];
}

这样我可以从我的中间件访问控制器的规则,并检查用户是否可以访问此路由,根据它是否已记录以及他是否具有授权角色之一。

【讨论】:

    猜你喜欢
    • 2017-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2014-05-19
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    相关资源
    最近更新 更多