Facebook 授权 URL 重写
Facebook authorization with URL rewrite
我花了一整天的时间解决这个问题,但无法解决...你能帮忙吗?
什么问题
我的 facebook(和 Google+)授权不起作用,如果我有 URL 重写活动。
它的表现如何
如果我访问 FB(或 G+)授权页面并同意授权,那么我将被重定向到我的应用程序并再次返回到 FB,我收到:
This webpage has a redirect loop
ERR_TOO_MANY_REDIRECTS
我的 Facebook 身份验证 class 的样子
在我的应用程序中,我使用此 class 登录 Facebook
<?php
namespace App\Presenters;
use Facebook\FacebookSession,
Facebook\FacebookRedirectLoginHelper,
Facebook\FacebookRequestException,
Facebook\GraphUser,
Facebook\FacebookRequest;
class FacebookPresenter extends BasePresenter {
/** @var \App\Model\UserManager @inject */
public $um;
/**
* Default facebook action
*/
public function actionDefault() {
// Start session
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Configuration
$appId = $this->context->parameters['facebook']['appId'];
$appSecret = $this->context->parameters['facebook']['appSecret'];
$scope = array('email');
// This producs always valid route based on router configuration
$loginRedirectUrl = $this->link('//Facebook:default');
FacebookSession::setDefaultApplication($appId, $appSecret);
$helper = new FacebookRedirectLoginHelper($loginRedirectUrl);
// Get facebook session
try {
$session = $helper->getSessionFromRedirect();
} catch(FacebookRequestException $ex) {
$this->redirectUrl($helper->getLoginUrl($scope));
} catch(\Exception $ex) {
$this->redirectUrl($helper->getLoginUrl($scope));
}
// Session was established
if ($session) {
try {
$req = new FacebookRequest($session, 'GET', '/me');
$userProfile = $req->execute()->getGraphObject(GraphUser::className());
$fbArr = $userProfile->asArray();
$fbId = $fbArr['id'];
$fbArr['picture'] = "https://graph.facebook.com/$fbId/picture?width=360&height=360";
// Login or register
$this->loginOrRegister($fbId, $fbArr);
// After facebook login redirect to homepage
$this->flashMessage("Facebook login was successful", "success");
$this->redirect('Homepage:');
} catch (FacebookRequestException $e) {
$this->redirectUrl($helper->getLoginUrl($scope));
}
// Session was not established
} else{
$this->redirectUrl($helper->getLoginUrl($scope));
}
}
/**
* Login or registers user
* @param String $fbId
* @param array $fbArr
*/
protected function loginOrRegister($fbId, $fbArr) {
// Try to login with given ID
try {
// Login
$this->user->login(NULL, NULL, $fbId, NULL);
// Try to update user's picture
if (isset($fbArr['picture']) && strlen($fbArr['picture']) > 0) {
$this->um->updateAvatar($fbArr['picture'], $fbId, null);
}
} catch (\Nette\Security\AuthenticationException $ex) {
// Retrieve social info
$email = isset($fbArr['email']) ? $fbArr['email'] : "";
$firstName = isset($fbArr['first_name']) ? $fbArr['first_name'] : "";
$lastName = isset($fbArr['last_name']) ? $fbArr['last_name'] : "";
$picture = isset($fbArr['picture']) ? $fbArr['picture'] : null;
// Check if there is user with acquired email
// If he/she is, then update his facebook ID and verify him/her and login
$tmpUser = $this->createDao("AppUser")->loadByEmail($email);
if ($tmpUser && $tmpUser->isPopulated()) {
$tmpUser->updateFbId($fbId);
$tmpUser->updateAvatar($picture, $fbId, null);
$tmpUser->verify($tmpUser->getVCode());
$this->user->login(NULL, NULL, $fbId, NULL);
} else {
// Send user to registration
$this->redirect('Sign:register', array(
'name' => ($firstName . " " . $lastName),
'email' => $email,
'fbId' => $fbId)
);
}
}
}
}
我的路由器配置如何
如果 rewrite 为 false,则简单路由器处于活动状态并且一切正常,否则不
/**
* @return \Nette\Application\IRouter
*/
public static function createRouter() {
$rewrite = true;
// Simple router
if (!$rewrite) {
return new SimpleRouter('Homepage:default');
}
// Full router list
$router = new RouteList();
$router[] = new Route('', array(
'presenter' => 'Homepage',
'action' => 'default',
));
$router[] = new Route('story', 'Homepage:story');
$router[] = new Route('feed', 'Homepage:feed');
$router[] = new Route('register', 'Sign:register');
$router[] = new Route('verify', 'Sign:verify');
$router[] = new Route('in', 'Sign:in');
$router[] = new Route('user/<id>', 'User:default');
$router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');
return $router;
}
我的 URL 长什么样
对于简单路由器:
https://www.facebook.com/v2.2/dialog/oauth?client_id=478905205596609&redirect_uri=http://localhost/~tester/testproject/www/?presenter=Facebook&state=4b63bfb3c9507c89347455663c2f5279&sdk=php-sdk-4.0.16&scope=email
对于重写的 url:
https://www.facebook.com/v2.2/dialog/oauth?client_id=478904678929995&redirect_uri=http://localhost/~tester/testproject/www/facebook/&state=536560378c582ddb17f0fe821cf20846&sdk=php-sdk-4.0.16&scope=email
更新 2015-06-12
我发现有问题的部分代码....如果 URL 重写处于活动状态,则
$session = $helper->getSessionFromRedirect();
始终为 null,因此代码始终转到 actionDefault 中的最后一个 else。因为我找到了这个主题 Why is getSessionFromRedirect() return a NULL? ... 但是,我以正确的顺序调用 getSessionFromRedirect 和 getLoginUrl 方法
这家伙做了一个 package 可能对你有帮助。
还有一个叫FacebookAuthenticator的class,主要问题是它没有文档,所以你只需要分析源代码就可以了。
祝你好运
我花了一整天的时间解决这个问题,但无法解决...你能帮忙吗?
什么问题
我的 facebook(和 Google+)授权不起作用,如果我有 URL 重写活动。
它的表现如何
如果我访问 FB(或 G+)授权页面并同意授权,那么我将被重定向到我的应用程序并再次返回到 FB,我收到:
This webpage has a redirect loop
ERR_TOO_MANY_REDIRECTS
我的 Facebook 身份验证 class 的样子
在我的应用程序中,我使用此 class 登录 Facebook
<?php
namespace App\Presenters;
use Facebook\FacebookSession,
Facebook\FacebookRedirectLoginHelper,
Facebook\FacebookRequestException,
Facebook\GraphUser,
Facebook\FacebookRequest;
class FacebookPresenter extends BasePresenter {
/** @var \App\Model\UserManager @inject */
public $um;
/**
* Default facebook action
*/
public function actionDefault() {
// Start session
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Configuration
$appId = $this->context->parameters['facebook']['appId'];
$appSecret = $this->context->parameters['facebook']['appSecret'];
$scope = array('email');
// This producs always valid route based on router configuration
$loginRedirectUrl = $this->link('//Facebook:default');
FacebookSession::setDefaultApplication($appId, $appSecret);
$helper = new FacebookRedirectLoginHelper($loginRedirectUrl);
// Get facebook session
try {
$session = $helper->getSessionFromRedirect();
} catch(FacebookRequestException $ex) {
$this->redirectUrl($helper->getLoginUrl($scope));
} catch(\Exception $ex) {
$this->redirectUrl($helper->getLoginUrl($scope));
}
// Session was established
if ($session) {
try {
$req = new FacebookRequest($session, 'GET', '/me');
$userProfile = $req->execute()->getGraphObject(GraphUser::className());
$fbArr = $userProfile->asArray();
$fbId = $fbArr['id'];
$fbArr['picture'] = "https://graph.facebook.com/$fbId/picture?width=360&height=360";
// Login or register
$this->loginOrRegister($fbId, $fbArr);
// After facebook login redirect to homepage
$this->flashMessage("Facebook login was successful", "success");
$this->redirect('Homepage:');
} catch (FacebookRequestException $e) {
$this->redirectUrl($helper->getLoginUrl($scope));
}
// Session was not established
} else{
$this->redirectUrl($helper->getLoginUrl($scope));
}
}
/**
* Login or registers user
* @param String $fbId
* @param array $fbArr
*/
protected function loginOrRegister($fbId, $fbArr) {
// Try to login with given ID
try {
// Login
$this->user->login(NULL, NULL, $fbId, NULL);
// Try to update user's picture
if (isset($fbArr['picture']) && strlen($fbArr['picture']) > 0) {
$this->um->updateAvatar($fbArr['picture'], $fbId, null);
}
} catch (\Nette\Security\AuthenticationException $ex) {
// Retrieve social info
$email = isset($fbArr['email']) ? $fbArr['email'] : "";
$firstName = isset($fbArr['first_name']) ? $fbArr['first_name'] : "";
$lastName = isset($fbArr['last_name']) ? $fbArr['last_name'] : "";
$picture = isset($fbArr['picture']) ? $fbArr['picture'] : null;
// Check if there is user with acquired email
// If he/she is, then update his facebook ID and verify him/her and login
$tmpUser = $this->createDao("AppUser")->loadByEmail($email);
if ($tmpUser && $tmpUser->isPopulated()) {
$tmpUser->updateFbId($fbId);
$tmpUser->updateAvatar($picture, $fbId, null);
$tmpUser->verify($tmpUser->getVCode());
$this->user->login(NULL, NULL, $fbId, NULL);
} else {
// Send user to registration
$this->redirect('Sign:register', array(
'name' => ($firstName . " " . $lastName),
'email' => $email,
'fbId' => $fbId)
);
}
}
}
}
我的路由器配置如何
如果 rewrite 为 false,则简单路由器处于活动状态并且一切正常,否则不
/**
* @return \Nette\Application\IRouter
*/
public static function createRouter() {
$rewrite = true;
// Simple router
if (!$rewrite) {
return new SimpleRouter('Homepage:default');
}
// Full router list
$router = new RouteList();
$router[] = new Route('', array(
'presenter' => 'Homepage',
'action' => 'default',
));
$router[] = new Route('story', 'Homepage:story');
$router[] = new Route('feed', 'Homepage:feed');
$router[] = new Route('register', 'Sign:register');
$router[] = new Route('verify', 'Sign:verify');
$router[] = new Route('in', 'Sign:in');
$router[] = new Route('user/<id>', 'User:default');
$router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');
return $router;
}
我的 URL 长什么样
对于简单路由器:
https://www.facebook.com/v2.2/dialog/oauth?client_id=478905205596609&redirect_uri=http://localhost/~tester/testproject/www/?presenter=Facebook&state=4b63bfb3c9507c89347455663c2f5279&sdk=php-sdk-4.0.16&scope=email
对于重写的 url:
https://www.facebook.com/v2.2/dialog/oauth?client_id=478904678929995&redirect_uri=http://localhost/~tester/testproject/www/facebook/&state=536560378c582ddb17f0fe821cf20846&sdk=php-sdk-4.0.16&scope=email
更新 2015-06-12
我发现有问题的部分代码....如果 URL 重写处于活动状态,则
$session = $helper->getSessionFromRedirect();
始终为 null,因此代码始终转到 actionDefault 中的最后一个 else。因为我找到了这个主题 Why is getSessionFromRedirect() return a NULL? ... 但是,我以正确的顺序调用 getSessionFromRedirect 和 getLoginUrl 方法
这家伙做了一个 package 可能对你有帮助。 还有一个叫FacebookAuthenticator的class,主要问题是它没有文档,所以你只需要分析源代码就可以了。
祝你好运