问题
I'm trying to setup FOSFacebookBundle and FOSUserBundle, so users can login with registered accounts or facebook accounts.
Here relevant codes:
config.yml:
fos_user:
db_driver: orm
firewall_name: public
user_class: Fam\DiaBundle\Entity\User
from_email:
address: info@famdia.com
sender_name: Staff
registration:
confirmation:
enabled: true
fos_facebook:
file: %kernel.root_dir%/../vendor/facebook/src/base_facebook.php
alias: facebook
app_id: 1234567890
secret: abcdefg1234567890
cookie: true
permissions: [email]
culture: us_US
security.yml
#
# app/config/security.yml
#
#
services:
my.facebook.user:
class: Fam\Dia\Security\User\Provider\FacebookProvider
arguments:
facebook: "@fos_facebook.api"
userManager: "@fos_user.user_manager"
validator: "@validator"
container: "@service_container"
security:
factories:
- "%kernel.root_dir%/../vendor/bundles/FOS/FacebookBundle/Resources/config/security_factories.xml"
providers:
chain_provider:
providers: [fos_userbundle, my_fos_facebook_provider]
fos_userbundle:
id: fos_user.user_manager
my_fos_facebook_provider:
id: my.facebook.user
encoders:
"FOS\UserBundle\Model\UserInterface": sha512
firewalls:
public:
pattern: ^/
fos_facebook:
app_url: "http://apps.facebook.com/dia/"
server_url: "http://diafam.com/facebookApp/"
login_path: /login
check_path: /login_check
default_target_path: /
provider: my_fos_facebook_provider
form_login:
login_path: /login
check_path: /login_check
provider: fos_userbundle
anonymous: true
logout: true
access_control:
- { path: ^/secured/.*, role: [IS_AUTHENTICATED_FULLY] } # This is the route secured with fos_facebook
- { path: ^/facebook/, role: [ROLE_FACEBOOK] }
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
# FOS facebook
- { path: ^/login_check, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/.*, role: [IS_AUTHENTICATED_ANONYMOUSLY] }
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
routing.yml
_security_check:
pattern: /login_check
_security_logout:
pattern: /logout
_security_login:
pattern: /login
FacebookProvider.php
<?php
// src/Fam\DiaBundle\Security\User\Provider/FacebookProvider.php
namespace Fam\DiaBundle\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 \BaseFacebook;
use \FacebookApiException;
class FacebookProvider implements UserProviderInterface
{
/**
* @var \Facebook
*/
protected $facebook;
protected $userManager;
protected $validator;
public function __construct(BaseFacebook $facebook, $userManager, $validator)
{
$this->facebook = $facebook;
$this->userManager = $userManager;
$this->validator = $validator;
}
public function supportsClass($class)
{
return $this->userManager->supportsClass($class);
}
public function findUserByFbId($fbId)
{
return $this->userManager->findUserBy(array('facebookId' => $fbId));
}
public function loadUserByUsername($username)
{
$user = $this->findUserByFbId($username);
try {
$fbdata = $this->facebook->api('/me');
} catch (FacebookApiException $e) {
$fbdata = null;
}
if (!empty($fbdata)) {
if (empty($user)) {
$user = $this->userManager->createUser();
$user->setEnabled(true);
$user->setPassword('');
}
// TODO use http://developers.facebook.com/docs/api/realtime
$user->setFBData($fbdata);
if (count($this->validator->validate($user, 'Facebook'))) {
// TODO: the user was found obviously, but doesnt match our expectations, do something smart
throw new UsernameNotFoundException('The facebook user could not be stored');
}
$this->userManager->updateUser($user);
}
if (empty($user)) {
throw new UsernameNotFoundException('The user is not authenticated on facebook');
}
return $user;
}
public function refreshUser(UserInterface $user)
{
if (!$this->supportsClass(get_class($user)) || !$user->getFacebookId()) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
return $this->loadUserByUsername($user->getFacebookId());
}
}
login.html.twig
{% extends '::base.html.twig' %}
{% block body %}
{{ facebook_initialize({'xfbml': true, 'fbAsyncInit': 'onFbInit();'}) }}
{{ facebook_login_button({'autologoutlink': true}) }}
<script>
function goLogIn(){
window.location.href = "{{ path('_security_check') }}";
}
function onFbInit() {
if (typeof(FB) != 'undefined' && FB != null ) {
FB.Event.subscribe('auth.statusChange', function(response) {
if (response.session || response.authResponse) {
setTimeout(goLogIn, 500);
} else {
window.location.href = "{{ path('_security_logout') }}";
}
});
}
}
</script>
{% for key, message in app.session.getFlashes() %}
<div class="{{ key }}">
{{ message|trans({}, 'FOSUserBundle') }}
</div>
{% endfor %}
{% if error %}
<div>{{ error }}</div>
{% endif %}
<form action="{{ path("fos_user_security_check") }}" method="post">
<h5><label for="username">{{ 'security.login.username'|trans({}, 'FOSUserBundle') }}</label><br/>
<input type="text" id="username" name="_username" value="{{ last_username }}" size=30 /><p>
<label for="password">{{ 'security.login.password'|trans({}, 'FOSUserBundle') }}</label><br/>
<input type="password" id="password" name="_password" size=30 /><p>
<input type="checkbox" id="remember_me" name="_remember_me" value="on" />
<label for="remember_me">{{ 'security.login.remember_me'|trans({}, 'FOSUserBundle') }}</label><p>
<input type="submit" id="_submit" name="_submit" value="Entra" />
</form>
</div>
{% endblock body %}
May you help me?
回答1:
Here the solution:
in routing.yml
_security_check:
pattern: /loginFb
in security.yml:
fos_facebook:
check_path: /loginFb
in default controller:
/**
* Dummy controller.
*
* @Route("/loginFb")
* @Template
*
*
* */
public function loginFbAction() {
}
回答2:
https://github.com/FriendsOfSymfony/FOSFacebookBundle/tree/2.0#include-the-login-button-in-your-templates says:
Note that we wait 500ms before redirecting to let the browser dealing with the Facebook cookie. You can avoid this step but you might get this error message: "The Facebook user could not be retrieved from the session."
来源:https://stackoverflow.com/questions/9046669/fosfacebookbundle-and-fosuserbundle