我正在尝试为我的Silex应用程序构建自定义身份验证系统。
这个想法是所有身份验证都将由单独的服务完成。我花了一天时间试图进入Silex \ Symfony认证机制,但不能说我做得很好: - \ 我发现这个Custom Authentication System with Guard教程对我来说很基础。使用它作为地下室我开始采用它来满足我的需求。 它一直有效,直到我尝试添加 form 位。
目前我的主要问题是它没有(或者我不明白该怎么做)在尝试访问安全区域时重定向到登录URL。我通过将硬编码重定向放入 TokenAuthenticator-> start()方法找到了一种解决方法,但它对我来说真的很糟糕。此外,在这种情况下,在成功验证后,它不会重定向到最初请求的URL。
有人可以告诉我我的代码中有什么问题(除非完全理解机制如何工作;或者至少描述Silex身份验证流程(从请求安全URL到成功验证后重定向)?请记住,我对Symfony完全不熟悉,因此他们的手册对我来说并不是很有用。
我的代码:
的index.php
<?
// bootstrap stuff here...
use Symfony\Component\HttpFoundation\Request;
$app->get('/login', function(Request $request) use ($app) {
return $app['twig']->render('login.twig', array(
'error' => $app['security.last_error']($request),
'last_username' => $app['session']->get('_security.last_username'),
));
});
$app['app.token_authenticator'] = function ($app) {
return new \CP\Classes\TokenAuthenticator($app['security.encoder_factory']);
};
$app['security.firewalls'] = array(
'secured' => array(
'pattern' => '^/safe/',
'form' => array('login_path' => '/login', 'check_path' => '/safe/login_check'),
'logout' => array('logout_path' => '/safe/logout', 'invalidate_session' => true),
'guard' => array(
'authenticators' => array(
'app.token_authenticator'
),
),
'users' => function () use ($app) {
return new \CP\Classes\OMSUserProvider($app);
},
),
);
$app->register( new Silex\Provider\SecurityServiceProvider() );
// blablabla
$app->run();
TokenAuthenticator.php
<?php
namespace CP\Classes;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
class TokenAuthenticator extends AbstractGuardAuthenticator {
private $encoderFactory;
public function __construct( EncoderFactoryInterface $encoderFactory ) {
$this->encoderFactory = $encoderFactory;
}
public function getCredentials( Request $request ) {
$username = $request->request->get('_username');
$request->getSession()->set(Security::LAST_USERNAME, $username);
$password = $request->request->get('_password');
return array(
'username' => $username,
'password' => $password
);
}
public function getUser( $credentials, UserProviderInterface $userProvider ) {
return $userProvider->loadUserByUsername( $credentials['username'] );
}
public function checkCredentials( $credentials, UserInterface $user ) {
$res = json_decode(file_get_contents('http://127.0.0.1:83/auth.php?u='.$user->getUsername().'&p='.$credentials['password']));
return $res->result;
}
public function onAuthenticationSuccess( Request $request, TokenInterface $token, $providerKey ) {
return;
}
public function onAuthenticationFailure( Request $request, AuthenticationException $exception ) {
$data = [ 'message' => strtr( $exception->getMessageKey(), $exception->getMessageData() )];
return new JsonResponse( $data, 403 );
}
/**
* Called when authentication is needed, but it's not sent
*/
public function start( Request $request, AuthenticationException $authException = null ) {
// Mentioned hardcoded redirect
// $app = new \Silex\Application();
// return $app->redirect('/login', 401);
$data = [ // you might translate this message
'message' => 'Authentication Required', ];
return new JsonResponse( $data, 401 );
}
public function supportsRememberMe() {
return false;
}
}
谢谢!
答案 0 :(得分:2)
虽然不是一个完整的答案,但这里有一些想法:
<强> TokenAuthenticator.php 强>
volumes: "{{ [{'device_name': '/dev/sdb'},{'device_name': '/dev/sdc'}] | map('combine',vol_default) | list }}"
<强>的index.php 强>
<?php
//...
use Symfony\Component\HttpFoundation\RedirectResponse;
class TokenAuthenticator extends AbstractGuardAuthenticator
{
private $encoderFactory;
private $login_url
public function __construct(EncoderFactoryInterface $encoderFactory , $login_url = '/login')
{
$this->encoderFactory = $encoderFactory;
$this->login_url = $login_url;
}
//...
/**
* Called when authentication is needed, but it's not sent
*/
public function start(Request $request, AuthenticationException $authException = null)
{
return new RedirectResponse($this->login_url, 401);
}
//...
}