【发布时间】:2016-08-12 23:59:04
【问题描述】:
我已经编写了自己的身份验证控制器来在我的 Slim 应用程序中执行用户身份验证。虽然它有效,但我不确定这是否是 Slim 的预期工作方式。
我的身份验证控制器$auth 具有更改会话状态的$auth->login($user, $password) 和$auth->logout() 等方法和报告状态的方法,例如$auth->userIsLoggedIn()。此外,给定一个请求,它可以确定用户是否有权访问请求的路由。
目前,我在我的 Slim 应用程序中以两种不同的方式使用 $auth 的单个实例:作为注册到 $app->auth 的单例,以及作为应用于所有路由的路由中间件。所以,Slim 应用程序是这样引导的:
// Create singleton instance of MyAuthWrapper
$app->auth = new MyAuthenticationWrapper( array() );
// Attach the same instance as middleware to all routes
$app->add( $app->auth );
我在我的路由中使用单例实例,例如,在登录路由中:
$app->post( '/login', function() use ($app)
{
// ...
$user = $app->auth->authenticate( $app->request()->post('username'), $app->request()->post('password') );
// ...
}
我在所有路由中使用中间件版本,方法是向slim.before.dispatch 钩子附加一个方法,验证用户是否经过身份验证,否则会重定向到登录页面。为此,身份验证包装器扩展了 \Slim\Middleware 并因此实现了call 方法,如下所示(简化):
class MyAuthenticationWrapper extends \Slim\Middleware
{
// ... Implementation of methods such as authenticate(), isLoggedIn(), logout(), etc.
public function call()
{
$app = $this->app;
$isAuthorized = function () use ($app) {
$hasIdentity = $this->userIsLoggedIn(); // Assume this to work
$isAllowed = $this->userHasAccessToRequestedRoute(); // Assume this to work
if ($hasIdentity && !$isAllowed)
{
throw new Exception("You have no access to this route");
}
if (!$hasIdentity && !$isAllowed)
{
return $app->redirect( $loginPath );
}
};
$app->hook('slim.before.dispatch', $isAuthorized);
$this->next->call();
}
}
使用单例对我来说有点code smell,但随后将单例实例添加为带有$app->add( $app->auth ) 的中间件感觉很脏。最后使用中间件向调度钩子注册一个闭包让我想知道整个策略对于一个名为 Slim 的框架来说是否不太复杂。但我不知道是否有更简单或更优雅的方式来完成我想要的。
问题:我是否走在正确的轨道上,还是我错过了一些关于 Slim 工作原理的东西,可以让我以不那么复杂的方式完成此任务?
【问题讨论】:
标签: php authentication singleton slim