我在使用安全防火墙和自定义用户提供程序登录时遇到了错误的凭据。 这是我的代码。
$app->register(new SecurityServiceProvider(), array(
'security.firewalls' => array(
'admin' => array(
'pattern' => '^/admin',
'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'),
'logout' => array('logout_path' => '/admin/logout'), // url to call for logging out
'users' => $app->share(function() use ($app) {
// Specific class user\UserProvider
return new UserProvider();
}),
)
),
'security.access_rules' => array(
// You can rename ROLE_ADMIN as you wish
array('^/admin', 'ROLE_ADMIN'),
)
));
$app['security.encoder.digest'] = $app->share(function ($app) {
// use the sha1 algorithm
// don't base64 encode the password
// use only 1 iteration
return new MessageDigestPasswordEncoder('sha1', false, 1);
});
我的路线:
$app->get("/login", "site\controllers\SiteController::login");
$app->post("/admin/login_check", "admin\controllers\AdminController::loginCheck");
我的sitecontroller功能:
public function login(Application $app, Request $request) {
return $app['twig']->render('site/views/login.html.twig', array(
'error' => $app['security.last_error']($request),
'last_username' => $app['session']->get('_security.last_username'),
));
}
我的观点:
<form action="{{ path('admin_login_check') }}" method="post">
{{ error }}
<input type="text" name="username" value="{{ last_username }}" />
<input type="password" name="password" value="" />
<input type="submit" />
</form>
我的数据库表:
id username password roles
1 admin d033e22ae348aeb5660fc2140aec35850c4da997 ROLE_ADMIN
我的自定义用户提供商:
<?php
namespace user\models;
use app\config\PDOFactory;
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;
class UserProvider extends PDOFactory implements UserProviderInterface {
public function loadUserByUsername($username)
{
$response = $this->db->prepare('SELECT * FROM users WHERE username = ?');
$response->execute(array(strtolower($username)));
if (!$user = $response->fetch()) {
throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
}
return new User($user['username'], $user['password'], 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';
}
}
我的数据库连接:
namespace app\config;
abstract class PDOFactory {
protected $db;
public function __construct()
{
$db = new \PDO('mysql:host=localhost;dbname=silex', 'root', '');
$db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->db = $db;
}
}
在登录尝试时,我不认为我从admincontroller访问loginCheck函数,因为它没有回显任何东西:
public function loginCheck(Application $app, Request $request) {
echo 'LOGIN-CHECK';
$username = $request->get('username');
$password = $request->get('password');
$password = $app['security.encoder.digest']->encodePassword($password, '');
$userProvider = new UserProvider();
$user = $userProvider->loadUserbyUsername($username);
if ($user->getPassword() == $password){
return $app['twig']->render('admin/views/index.html.twig');
}
else{
return $app['twig']->render('site/views/login.html.twig', array(
'error' => $app['security.last_error']($request),
'last_username' => $app['session']->get('_security.last_username'),
));
}
}
我的密码是'admin',我使用此代码为数据库表生成密码:
echo $app['security.encoder.digest']->encodePassword('admin', '');
你能告诉我有什么问题吗?
编辑: 我的错误在于我的观点,它没有在帖子名称之前使用下划线
<form action="{{ path('admin_login_check') }}" method="post">
{{ error }}
<input type="text" name="_username" value="{{ last_username }}" />
<input type="password" name="_password" value="" />
<input type="submit" />
</form>
我不需要login_check路径的任何路由或任何控制器功能。它由安全防火墙管理。 谢谢你的帮助!
答案 0 :(得分:2)
首先,启用日志记录(通过monolog provider并设置$app['debug'] = true;
并检查日志,如果启用了记录,安全组件会大量提供信息。
其次,您不必为 check_path ,does it for you和{{创建控制器(甚至不是路由,安全提供程序the kernel traps all incoming request to this path) 3}}(只要您不覆盖默认的身份验证提供程序,但您不想仅仅因为使用登录表单而去那条路线)。
说完并调试代码后,您可以尝试checks if the credentials are valid,一旦这个工作正常,再将其更改回来(当然,您需要更新数据库表上的密码字段) ,但很可能日志会告诉你发生了什么(如果你仍然丢失了日志,也只是发布它。)