bitgrave/persona-bundle

将Mozilla Persona身份验证服务集成到您的Symfony2应用程序中。

安装: 17

依赖: 0

建议者: 0

安全: 0

星标: 2

关注者: 0

分支: 3

开放问题: 0

类型:symfony-bundle

1.0.0 2013-08-28 08:47 UTC

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个步骤

  1. 用户必须有一个有效的个人身份验证账户
  2. 您必须触发symfony2登录
  3. 在您的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...