bitgrave / persona-bundle
将Mozilla Persona身份验证服务集成到您的Symfony2应用程序中。
Requires
- php: >=5.3.2
- symfony/framework-bundle: >=2.1,<2.3-dev
- symfony/security-bundle: >=2.1,<2.3-dev
- symfony/twig-bundle: >=2.1,<2.3-dev
This package is not auto-updated.
Last update: 2024-09-14 13:49:50 UTC
README
此Bundle允许集成Mozilla的PERSONA验证API。它还提供了一个Symfony2身份验证提供者,以便用户可以通过Persona的远程验证API登录到Symfony2。此外,通过自定义用户提供者支持,Persona登录也可以与其他数据源集成,例如著名的FOSUserBundle提供的基于数据库的解决方案。
请注意,登录用户需要3个步骤
- 用户必须有一个有效的个人身份验证账户
- 您必须触发symfony2登录
- 在您的login.html.twig模板或其他您喜欢的位置添加Persona登录按钮(twig辅助工具)
在我们的示例代码中,以下假设我们的本地Web服务器在http://dev.example.com下可访问。请将此域名更改为我们这里的开发基础服务器。
关于Persona验证API的更多信息可以在https://mdn.org.cn/de/docs/persona找到
请参阅SecurityBundle的官方文档,特别是关于配置的详细信息:https://symfony.ac.cn/doc/current/book/security.html
先决条件
此版本需要Symfony 2.1
安装
1 - 在您的composer.json中添加以下行
{
"require": {
"bitgrave/persona-bundle": "dev-master"
}
}
2 - 运行composer以下载此Bundle
$ php composer.phar update bitgrave/persona-bundle
3 - 将此Bundle添加到您的应用程序内核中
// app/ApplicationKernel.php
public function registerBundles()
{
return array(
// ...
new BG\PersonaBundle\BGPersonaBundle(),
// ...
);
}
4 - 在您的配置中配置persona
服务
# application/config/config.yml
bg_persona:
verifier_url: 'https://verifier.login.persona.org/verify'
audience_url: 'dev.example.com'
4.1. 如果要使用security component
,请添加此配置并定义一个自定义用户提供者类,将其用作提供者或定义登录路径(您可以替换给定的名称my_persona.persona_provider为任何其他(不同的)名称)...
# application/config/config.yml
security:
my_persona.persona_provider:
id: my_persona.persona.user
firewalls:
main:
bg_persona:
default_target_path: /
provider: my_persona.persona_provider
login_path: /login
check_path: /persona_login_check
5 - 为persona登录处理程序添加路由
# application/config/routing.yml
_persona_security_check:
pattern: /persona_login_check
6 - (可选)在您的parameters.yml中添加persona host-ident配置。此步骤并非真的必要,您可以将您的host identification放在config.yml中(_bg_persona:)
# application/config/parameters.yml
webapp_url: http://www.example.com
webapp_url_ssl: https://www.example.com
7 - 在您的LoginController文件中放置此占位符控制器。此代码假设您已安装并实现了sendio FrameworkExtraBundle(Route和Template模块),如果没有,请在您的默认routing.yml文件中设置person路由(/persona_login_check)。
/**
* persona logincheck dummy controller.
*
* @Route("/persona_login_check")
* @Template
*
* */
public function personaLoginCheckAction()
{
return array();
}
在您的模板中包含Persona登录按钮
在您的登录模板中添加以下代码(这是一个Persona CSS3按钮的twig示例)
<!-- inside your login twig template -->
{{ persona_login_button() }}
使用BG\PersonaBundle的示例自定义用户提供者
这需要为自定义用户提供者添加一个服务,然后将其设置为config.yml中“provider”部分中的提供者ID
my_persona.persona.user:
class: Nmq\UserBundle\Security\User\Provider\PersonaProvider
arguments:
persona: "@bg_persona.service"
userManager: "@fos_user.user_manager"
validator: "@validator"
session: "@session"
container: "@service_container"
自定义用户提供者类
<?php
namespace Acme\MyBundle\Security\User\Provider;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use BG\PersonaBundle\Services\BasePersona;
use Symfony\Component\HttpFoundation\Session;
class PersonaProvider implements UserProviderInterface
{
protected $userManager;
protected $validator;
protected $session;
protected $persona;
public function __construct(BasePersona $persona, $userManager, $validator, $session)
{
$this->persona = $persona;
$this->userManager = $userManager;
$this->validator = $validator;
$this->session = $session;
}
// main auth entry point, load user on exist, create user on non-existance
public function loadUserByUsername($p_persona_email)
{
$user = $this->findUserByPersonaId($p_persona_email);
$t_persona_email = $this->session->get('persona_email');
$t_persona_status = $this->session->get('persona_status');
$t_persona_expires = $this->session->get('persona_expires');
// compare persona expires microtimestamp with current one ...
if (($t_persona_status==='okay')&&($t_persona_expires>=round((microtime(true) * 1000))))
{
if (empty($user))
{
$user = $this->userManager->createUser();
$user->setEnabled(true);
$user->setPassword('');
}
$user->setPersonaId($t_persona_email);
$user->setPersonaLastStatus($t_persona_status);
$user->addRole('ROLE_PERSONA_USER');
$user->setPersonaExpires($t_persona_expires);
$this->userManager->updateUser($user);
// kill old persona session stack
$this->session->set('persona_email', null);
$this->session->set('persona_expires', null);
$this->session->set('persona_status', null);
}
if (empty($user)) {
throw new UsernameNotFoundException('The user is not authenticated on persona');
}
return $user;
}
public function findUserByPersonaId($personaEmail)
{
return $this->userManager->findUserBy(array('persona_email' => $personaEmail));
}
public function refreshUser(UserInterface $user)
{
if (!$this->supportsClass(get_class($user)) || !$user->getPersonaEmail()) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
return $this->loadUserByUsername($user->getPersonaEmail());
}
public function supportsClass($class)
{
return $this->userManager->supportsClass($class);
}
最后,还需要向用户模型添加getPersonaId()和setPersonaId()方法。请注意,字段first name和last name对于我们的Persona Bundle实现来说并非真的必要。以下示例使用Doctrine ORM + FOSUserBundle
<?php
namespace Acme\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Entity\User as BaseUser;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Nmq\UserBundle\Entity\User
* @ORM\Table(name="nmq_user")
* @ORM\Entity(repositoryClass="Nmq\UserBundle\Entity\UserRepository")
* @Gedmo\SoftDeleteable(fieldName="deletedAt")
*
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// //////////////////////////////////////
/**
* @var string $firstname
*
* @ORM\Column(name="firstname", type="string", length=80, nullable=true)
*/
protected $firstname;
/**
* @var string $lastname
*
* @ORM\Column(name="lastname", type="string", length=80, nullable=true)
*/
protected $lastname;
/**
* @param string $persona_lastStatus
*/
public function setPersonaLastStatus($persona_lastStatus)
{
$this->persona_lastStatus = $persona_lastStatus;
}
/**
* @return string
*/
public function getPersonaLastStatus()
{
return $this->persona_lastStatus;
}
/**
* @param string $persona_lastFailReason
*/
public function setPersonaLastFailReason($persona_lastFailReason)
{
$this->persona_lastFailReason = $persona_lastFailReason;
}
/**
* @return string
*/
public function getPersonaLastFailReason()
{
return $this->persona_lastFailReason;
}
public function setPersonaExpires($persona_expires)
{
$this->persona_expires = $persona_expires;
}
public function getPersonaExpires()
{
return $this->persona_expires;
}
/**
* @param string $persona_email
*/
public function setPersonaEmail($persona_email)
{
$this->persona_email = $persona_email;
}
/**
* @return string
*/
public function getPersonaEmail()
{
return $this->persona_email;
}
/**
* @var string $persona_email
*
* @ORM\Column(name="persona_email", type="string", length=255, nullable=true)
*/
protected $persona_email;
/**
* @ORM\Column(name="persona_expires", type="integer", nullable=true)
*/
protected $persona_expires;
/**
* @var string persona_lastStatus
* @ORM\Column(name="persona_last_status", type="string", length=8, nullable=true)
*/
protected $persona_lastStatus;
/**
* @var string persona_lastFailReason
* @ORM\Column(name="persona_last_fail_reason", type="string", nullable=true)
*/
protected $persona_lastFailReason;
// //////////////////////////////////////
/**
* Set lastname value for user
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
}
/**
* Get lastname value for user
* @return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* Set firstname value for user
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
}
/**
* Get firstname value for user
* @return string
*/
public function getFirstname()
{
return $this->firstname;
}
// //////////////////////////////////////
/***
* Set users personaId
*
* @param $persona_email
*/
public function setPersonaId($persona_email)
{
$this->email = $persona_email;
$this->emailCanonical = $this->email;
$this->setUsername($this->email);
$this->setPersonaEmail($this->email);
$this->salt = '';
}
/**
* Get the full name of the user (first + last name)
* @return string
*/
public function getFullName()
{
return $this->getFirstName() . ' ' . $this->getLastname();
}
// //////////////////////////////////////
public function __construct()
{
parent::__construct();
}
}
如何贡献
要贡献更改、修复、新增功能或特性,请提交包含您新代码的pull request。请注意,如果您添加了新功能或修改了现有功能,您必须在项目的README文件中记录此信息(还更新项目的CHANGELOG文件!)
许可
参见:resources/meta/LICENSE.md
致谢
该组件的结构和文档部分基于FriendsOfSymfony的FOSFacebookBundle。对于任何开放性问题或问题,请随时直接联系我或直接提交一个issue...