sf框架提供了一个强大的安全验证组件security,使用这个组件,可以不用写登录验证的代码,就能实现登录功能.
本文尽量用的是初学者易懂的语言来描述
具体步骤如下:
1.建立登录帐号数据表(user)
2.生成映射文件,实体类,参考http://blog.csdn.net/baby97/article/details/51248159
3.实体类需要实现UserInterface接口.以及接口中相应的抽象方法.
此处的getRoles()方法返回的固定值,可以根据实际情况,换成用户的动态权限.
getSalt()密文盐值,本例使用bcrypt加密,不需要盐值,所以返回null.
namespace CommonBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* AdminUser
*
* @ORM\Table(name="admin_user")
* @ORM\Entity(repositoryClass="CommonBundle\Repository\AdminUserRepository")
*/
class AdminUser extends CommonEntity implements UserInterface
{
public function getRoles()
{
// TODO: Implement getRoles() method.
return ['ROLE_ADMIN'];
}
public function getSalt()
{
return null;
// TODO: Implement getSalt() method.
}
public function getUsername()
{
return $this->name;
// TODO: Implement getUsername() method.
}
public function getPassword()
{
return $this->pwd;
// TODO: Implement getPassword() method.
}
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=50, nullable=true)
*/
private $name;
/**
* @var string
*
* @ORM\Column(name="pwd", type="string", length=200, nullable=true)
*/
private $pwd;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return AdminUser
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set pwd
*
* @param string $pwd
*
* @return AdminUser
*/
public function setPwd($pwd)
{
$this->pwd = $pwd;
return $this;
}
/**
* Get pwd
*
* @return string
*/
public function getPwd()
{
return $this->pwd;
}
}
4.配置app/config/security.yml
encoders:加密方式,此处使用bcrypt
providers:登录的实体类,property为登录用户名
firewalls:防火墙,指定了没有通过验证的地址和登录验证的地址以及登录成功后跳转地址.
access_control:设定哪些路径启动防火墙功能.IS_AUTHENTICATED_ANONYMOUSLY为允许非登录状态下访问的URL(注意:需要把/login_check设置为防火墙以外,允许非登录下访问.path为正则表达式,匹配了/login_check地址)
security:
encoders:
CommonBundle\Entity\AdminUser: bcrypt
providers:
main:
entity: { class: CommonBundle:AdminUser, property: name }
firewalls:
main:
pattern: /.*
form_login:
check_path: /login_check
login_path: /login
default_target_path: /index
logout: true
security: true
anonymous: true
access_control:
- { path: /login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /.*, role: ROLE_ADMIN }
5.实现loginAction
注意下面的login_check方法,是个空的,我在看相关教程时,有的教程说login_check不用实现,系统会自动识别创建,我试过,报错.有的教程说需要建个空方法.
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
/**
* @Route("/login",name="login_form")
* @Template()
*/
public function loginAction(Request $request){
$curUser = $this->getUser();
if ($curUser) {
return $this->redirectToRoute("user_index");
}
$session = $request->getSession();
// get the login error if there is one
if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
Security::AUTHENTICATION_ERROR
);
} elseif (null !== $session && $session->has(Security::AUTHENTICATION_ERROR)) {
$error = $session->get(Security::AUTHENTICATION_ERROR);
$session->remove(Security::AUTHENTICATION_ERROR);
} else {
$error = '';
}
// last username entered by the user
$lastUsername = (null === $session) ? '' : $session->get(Security::LAST_USERNAME);
return array(
// last username entered by the user
'last_username' => $lastUsername,//$session->get(SecurityContextInterface::LAST_USERNAME),
'error' => $error,
);
}
/**
* @Route("/login_check",name="login_check")
* @Method({"POST","GET"})
*/
public function doLoginAction(Request $request){
}
6.建立login模板.
用户名和密码的name必须为:_username和_password
可以在配置里修改,但我没有偿试,有兴趣的可以试下.
form_login:login_path: /login
check_path: /checkLogin
default_target_path: /home
username_parameter: _username
password_parameter: _password
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
<form action="{{ path('login_check') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
{#
If you want to control the URL the user
is redirected to on success (more details below)
<input type="hidden" name="_target_path" value="/account" />
#}
<button type="submit">login</button>
</form>
到此,基本就实现了security方式的登录.
7.退出登录
实现退出就相对容易些,做如下配置就可以了:
security.yml
firewalls:
main:
pattern: /.*
form_login:
check_path: /login_check
login_path: /login
default_target_path: /index
logout:
path: /logout
target: /
security: true
anonymous: true
routing.yml
logout:
path: /logout