我正在使用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.
有任何建议使这项工作?
答案 0 :(得分:0)
要访问中间件中的容器,您可以执行以下操作:
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骨架,我使用这种技术&amp; amp; oAuth2身份验证以及我在每个控制器中定义路由安全性的位置。您可以查看它是否对您有所帮助:https://github.com/mickaeleuranie/slim-api(当我有时间的时候,我会添加JWT和通话比率)
我所做的是通过定义一个受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' => ['?'],
],
];
}
通过这种方式,我可以从我的中间件访问控制器的规则,并检查用户是否可以访问此路由,具体取决于是否已记录,以及是否拥有其中一个授权角色。 / p>