Benutzer-Authentifizierung mit einer db-backed UserProvider in Silex
Ich bin die Entwicklung einer Silex-Anwendung, und jetzt bin ich in der Sicherheits-phase. Ich habe gelesen das alle Unterlagen, die ich gefunden habe im Netz über dieses Thema, aber ich habe viele Zweifel, und ich wünschte, jemand würde mir helfen, wenn möglich.
Im Grunde folgte ich dieses tutorial von Johann Reinke.
... und natürlich die Silex-Dokumentation:
Auch alles, was ich über Google gefunden.
Aber dennoch denke ich, Silex noch fehlt eine Menge an Dokumentation, ich bin verloren, in vielerlei Hinsicht.
Mein code:
$app->register(new Silex\Provider\SessionServiceProvider(), array(
'session.storage.save_path' => __DIR__.'/../vendor/sessions',
));
$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
'db.options' => array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'dbname',
'user' => 'someuser',
'password' => 'somepass',
'charset' => 'utf8',
),
));
$app['security.encoder.digest'] = $app->share(function ($app) {
return new MessageDigestPasswordEncoder('sha1', false, 1);
});
$app['security.firewalls'] = array(
'acceso' => array(
'pattern' => '^/confirmar',
'form' => array('login_path' => '/acceso', 'check_path' => '/confirmar/comprobar_acceso'),
'logout' => array('logout_path' => '/confirmar/salir'),
'users' => $app->share(function() use ($app) {
return new Acme\User\UserProvider($app['db']);
}),
),
);
$app->register(new Silex\Provider\SecurityServiceProvider(array(
'security.firewalls' => $app['security.firewalls'],
'security.access_rules' => array(
array('^/confirmar', 'ROLE_USER'),
),
)));
Ich habe so viele Zweifel in die Steuerung:
$app->match('/acceso', function(Request $request) use ($app) {
$username = $request->get('_username');
$password = $request->get('_password');
if ('POST' == $request->getMethod())
{
$user = new Acme\User\UserProvider($app['db']);
$encoder = $app['security.encoder_factory']->getEncoder($user);
//compute the encoded password
$encodedPassword = $encoder->encodePassword($password, $user->getSalt());
//compare passwords
if ($user->password == $encodedPassword)
{
//set security token into security
$token = new UsernamePasswordToken($user, $password, '', array('ROLE_USER'));
$app['security']->setToken($token);
//return $app->redirect('/jander');
//redirect or give response here
} else {
//error feedback
}
}
return $app['twig']->render('login.twig', array(
'error' => $app['security.last_error']($request),
'last_username' => $app['session']->get('_security.last_username'),
));
})
->bind('acceso');
Dies ist meine Klasse, die Benutzer Anbieter:
//src/Acme/User/UserProvider.php
namespace Acme\User;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\DBAL\Connection;
class UserProvider implements UserProviderInterface
{
private $conn;
public function __construct(Connection $conn)
{
$this->conn = $conn;
}
public function loadUserByUsername($username)
{
$stmt = $this->conn->executeQuery('SELECT * FROM compradores WHERE idemail = ?', array(strtolower($username)));
if (!$user = $stmt->fetch()) {
throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
}
return new User($user['idemail'], $user['pass'], explode(',', $user['roles']), true, true, true, true);
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'Symfony\Component\Security\Core\User\User';
}
}
Und meine form:
<form action="{{ path('confirmar_comprobar_acceso') }}" method="post">
{{ error }}
<input type="text" name="_username" value="{{ last_username }}" />
<input type="password" name="_password" value="" />
<input type="submit" />
</form>
- Und das ist meine mysql Tabelle:
id int(15)
idemail varchar(255)
nombre varchar(255)
apellidos varchar(255)
telefono int(11)
activo tinyint(4)
pass varchar(40)
roles varchar(255)
iva tinyint(4)
nifcif varchar(255)
Bekomme ich immer ein "Bad credentials" Antwort beim login-Versuch. Irgendwelche Ideen? Vielen Dank und Cheers!
- Der erste link oben ist entweder gebrochen, oder enthält einen virus (mein firefox nur verrückt). Kann man es abnehmen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Bei 40 Zeichen, Ihre Passwort-Feld "pass" ist wohl das abschneiden der verschlüsselten Passwörter. Versuchen Sie, das Feld auf varchar(255)
Ich hatte ein ähnliches problem mit dem Standard-encoder, was ich vermute, war in Bezug auf die Datenbank-Sortierung oder vielleicht mehrere base64-Kodierungen.
Ersetzte ich es mit einfachen sha1-ziemlich unsicher, aber das gibt eine Allgemeine Idee (Sie können ersetzen es mit sha2, um auf der sicheren Seite). Fügen Sie diese nach der Registrierung Ihres security-Anbieter:
Und Sie haben zu stellen Sie sicher, dass Ihre gespeicherten Passwörter zu verwenden, die den gleichen Hash-Algorithmus.