- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我构建了一个非常简单的 CakePHP 应用程序来测试 Facebook PHP SDK 的可能实现,用户可以使用该应用程序或 Facebook 注册,也可以使用该应用程序或 Facebook 登录。但由于用户可以在应用程序上执行操作,因此即使他们通过 Facebook 帐户登录/注册,他们也会在应用程序上拥有一个用户帐户。
到目前为止,我已经创建了处理身份验证和获取用户信息的两种方法:
// Asks user to authenticate
public function facebook()
{
$params = array(
'redirect_uri' => 'http://domain.com/users/signupfacebook',
'scope'=> 'email',
'display' => 'popup'
);
$loginUrl = $this->Facebook->Sdk->getLoginUrl($params);
// Need to know if user is already a user on OUR app
// If true log them in. If false redirect to signup form like below
$this->autoRender = false;
$this->response->header('Location', $loginUrl);
}
// Handle the return
public function signupfacebook()
{
$user = $this->Facebook->Sdk->getUser();
if($user)
{
try
{
$facebookuser = $this->Facebook->Sdk->api('/me');
$this->set('facebookuser', $facebookuser);
}
catch(FacebookApiException $e)
{
error_log($e);
$user = NULL;
}
}
else
{
$this->Session->setFlash('An error has occurred! Please try again.');
$this->redirect(array('action'=>'index'));
}
}
所以用户说我想使用 Facebook 进行身份验证,这使用了我的 Controller 的 facebook() 方法,然后它将请求他们的许可并根据此操作重定向他们。目前它只会将他们发送到一个注册页面,其中一些字段是根据他们传递的用户信息预先填写的,如下所示:
<?php echo $this->Form->create('User'); ?>
<?php echo $this->Form->input('User.email', array('type' => 'text', 'default'=> $facebookuser['email'], 'label' => array('class' => 'placeholder', 'text' => 'Email address') )); ?>
<?php echo $this->Form->input('User.firstname', array('type' => 'text', 'default'=> $facebookuser['first_name'], 'label' => array('class' => 'placeholder', 'text' => 'Firstname') )); ?>
<?php echo $this->Form->input('User.lastname', array('type' => 'text', 'default'=> $facebookuser['last_name'], 'label' => array('class' => 'placeholder', 'text' => 'Lastname') )); ?>
<?php echo $this->Form->input('User.username', array('type' => 'text', 'default'=> $facebookuser['username'], 'label' => array('class' => 'placeholder', 'text' => 'Username') )); ?>
<?php echo $this->Form->input('User.password', array('value' => '','type' => 'password', 'label' => array('class' => 'placeholder', 'text' => 'Password') )); ?>
<button type="submit">Create</button>
<?php echo $this->Form->end(); ?>
但我这里有几个问题:
问题 1.) 如果用户已经在系统中使用他们刚刚输入的 Facebook 凭据创建了一个帐户,那么它需要处理这个问题并让用户登录。这是否需要使用Facebook 端有什么特别之处吗?因为我正在考虑只在用户表中搜索匹配的帐户,然后自动登录它们,但是我没有在网上找到任何在 FB 身份验证发生后对您自己的用户表进行身份验证的示例。
问题 2.) 可能与上一个问题相关,但是当用户注册帐户时,不会保存与他们用于登录的 Facebook 帐户的关联,因此如果他们尝试再次登录时使用除非我在数据库中搜索类似的详细信息,否则不会看到 Facebook 关联,但这又一次看起来很古怪,而不是 API 的正确使用。本质上,用户只是使用 FB 填写了一个表格,并没有实际使用他们的 Facebook 帐户进行注册。
我可以检查数据库中是否存在与通过 Facebook 传递的电子邮件地址相同的电子邮件地址,但如果他们更改了该地址怎么办?我考虑过可能将 Facebook 用户 ID 存储在一个表中,该表中包含应用程序中的用户 ID,以便存储连接。这是一个解决方案吗?还是错误的方法?
例如一个新表,用于存储 FB 用户和 CakePHP 应用程序用户之间的链接:
id
user_id (this is the relationship to your USER table)
facebook_user_id
但即使这样做,我也不确定我将如何利用它以有用的方式正确链接帐户并正确处理通过 Facebook 的身份验证,而不是仅仅自动填充表单或在某些情况下让用户登录细节匹配(我确信这有潜在的安全风险)。
问题 3.) 当用户通过 Facebook 返回到注册表单时,他们会收到以下 URL(注意位已出于安全原因进行了更改):
http://domain.com/users/signupfacebook?state=dbf2f6dds322b7cb90d71b6c958a001bf4a3ba&code=AQa7-GDsesM0ZfgswjgGF-mMKwjcoboLl19WKprIA2-f4iZzUdsd8o8z-NweYYODzySS3h9GksBw0G9WCXj79Pp-0ldyeIRCOLSt9gfgfsmEFEfOrEO6gm7a0jmDuQvchdsaHaw1QpI8RdGTCrqAPlLzpHGcqiCtBvXjiQtBhQP--tMr8CIlvRwbrJRwiZwF6xo30howlRkVTLddsdDCDt60_KGznPVmEe-T4Qbu9gdkv9v#_=_
据我所知:https://developers.facebook.com/docs/howtos/login/server-side-login/我应该在上面发布的两种方法之间创建一个额外的步骤来处理代码并取回访问 token 。
但我已经访问了填写注册表单所需的所有必需信息,而无需执行 OAuth 流程的第二阶段并获取访问 token !所以不确定我是否需要它这种情况……还是我?如果是的话,它如何帮助解决前两个问题?
最佳答案
以下是允许用户通过 facebook
注册的步骤。
我用来完成这个任务的表结构如下,
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`email` varchar(255) NOT NULL,
`password` varchar(200) NOT NULL,
`profile_name` varchar(100) NOT NULL,
`dob` date NOT NULL,
`phone_number` bigint(20) NOT NULL,
`location` varchar(200) NOT NULL,
`user_picture` varchar(200) NOT NULL,
`profile_view` bigint(20) NOT NULL,
`facebook_id` bigint(11) NOT NULL,
`facebook_status` tinyint(4) NOT NULL,
`login_status` tinyint(4) NOT NULL,
`status` tinyint(4) NOT NULL,
`activation_link` varchar(200) NOT NULL,
`password_link` varchar(200) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
首先创建包含以下代码的 View 文件。我把它放在 views/users/signup.ctp
<div class="grid_7 alpha">
<a href="Javascript:void(0);" onclick="connect_facebook(); return false;">
Signup with facebook
</a>
</div>
应用一些 CSS 使其看起来更漂亮。现在在同一 View 文件中,在页面底部添加以下代码。
<script type="text/javascript">
window.fbAsyncInit = function()
{
FB.init(
{
appId: FACEBOOK_API,
cookie: true,
xfbml: true,
oauth: true
});
};
function connect_facebook()
{
FB.login(function(response)
{
if (response.authResponse)
{
$.ajax(
{
url : HOST+'users/facebook_signup/'+response.authResponse.userID,
dataType : 'json',
beforeSend : function()
{
$.blockUI({
message: '<img src="'+HOST+'img/popup/pre_code_bg.gif" alt="" />'
});
},
success : function(data)
{
$.unblockUI();
if(data.status == "false")
{
FB.logout(function(response)
{
window.location = HOST+'users/logout';
});
return false;
}
else
{
document.location.reload(true);
}
}
});
}
else
{
FB.logout(function(response)
{
window.location = HOST+'users/logout';
alert('User cancelled login or did not fully authorize.');
});
}
});
}
(function()
{
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-signup-root').appendChild(e);
}());
</script>
只需相应地替换 FACEBOOK_API
。
现在在 users_controller
文件中粘贴下面的代码,
<?php
class UsersController extends AppController
{
var $name = 'Users';
function beforeFilter()
{
parent::beforeFilter();
$this->Auth->allow( 'login','signup''facebook_signup' );
}
function facebook_signup($facebook_id)
{
$this->autoRender = false;
$this->layout = "ajax";
App::import('Vendor', 'Facebook', array('file' => 'facebook'.DS.'facebook.php'));
$response = array();
$facebook = new Facebook(array
(
'appId' => FACEBOOK_API,
'secret' => FACEBOOK_SKEY,
));
$facebook_user = $facebook->getUser();
if ($facebook_user)
{
try
{
$user_profile = $facebook->api('/me');
}
catch (FacebookApiException $e)
{
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
$facebook_user = null;
}
}
$find_facebookemail = $this->User->find('first',array
(
'conditions' => array
(
'User.email' => $user_profile['email'],
'OR' => array
(
'User.facebook_id' => 0,
'User.facebook_id' => $facebook_id
)
),
'recursive' => -1
));
if(!empty($find_facebookemail))
{
$this->data['User']['id'] = $find_facebookemail['User']['id'];
$this->data['User']['email'] = $find_facebookemail['User']['email'];
$this->data['User']['name'] = $find_facebookemail['User']['name'];
$this->data['User']['facebook_id'] = $find_facebookemail['User']['facebook_id'];
$this->data['User']['location'] = $find_facebookemail['User']['location'];
$this->data['User']['dob'] = $find_facebookemail['User']['dob'];
$this->Session->write("Auth.User", $find_facebookemail['User']);
$this->Session->write("Auth.User.facebook_user", true);
$response['status'] = "true";
echo json_encode($response);
exit;
}
else
{
$this->data['User']['email'] = $user_profile['email'];
$this->data['User']['name'] = $user_profile['name'];
$this->data['User']['facebook_id'] = $user_profile['id'];
$this->data['User']['location'] = $user_profile['location']['name'];
$this->data['User']['facebook_status'] = 1;
$this->data['User']['status'] = 1;
$dob = explode("/",$user_profile['birthday']);
$this->data['User']['dob'] = $dob[2].'-'.$dob[0].'-'.$dob[1];
if($this->User->save($this->data['User']))
{
$this->Session->write("Auth.User.id", $this->User->getLastInsertID());
$this->Session->write("Auth.User.name", $this->data['User']['name']);
$this->Session->write("Auth.User.email", $this->data['User']['email']);
$this->Session->write("Auth.User.facebook_id", $this->data['User']['facebook_id']);
$this->Session->write("Auth.User.location", $this->data['User']['location']);
$this->Session->write("Auth.User.dob", $this->data['User']['dob']);
$this->Session->write("Auth.User.facebook_user", true);
$img = file_get_contents('https://graph.facebook.com/'.$find_facebookemail['User']['facebook_id'].'/picture?width=500&height=500');
$img_thumbs = file_get_contents('https://graph.facebook.com/'.$find_facebookemail['User']['facebook_id'].'/picture?width=150&height=150');
$file = "img".DS."user_picture".DS."".$find_facebookemail['User']['facebook_id'].".jpg";
$file_thumbs = "img".DS."user_picture".DS."thumbs".DS."".$find_facebookemail['User']['facebook_id'].".jpg";
file_put_contents($file, $img);
file_put_contents($file_thumbs, $img_thumbs);
$this->data['User']['id'] = $this->Session->read('Auth.User.id');
$this->data['User']['user_picture'] = $find_facebookemail['User']['facebook_id'].".jpg";
$this->User->save($this->data['User']);
$response['message'] = "You have successfully registered with us.";
$response['status'] = "true";
echo json_encode($response);
exit;
}
else
{
$response['message'] = "Something is wrong during process.Please try again later.";
$response['status'] = "false";
echo json_encode($response);
exit;
}
}
exit;
}
}
Controller 代码所做的是检查是否有发布 ID 的 facebook
用户已经注册 然后允许他登录
到站点并设置 cakephp auth.user session 如果没有,则将用户和他/她的照片以及所有其他数据添加到 mysql 数据库中。
现在您的数据库中有用户条目,因此您可以要求用户更改他的密码,一旦他/她更改了密码,他们就可以login
到您的应用程序,而无需 login
in到 facebook
帐户。
以上代码经过了不止一次的全面测试并且可以正常工作。
完成。
关于php - 如果已通过身份验证并且用户存在于数据库中,则将 Facebook 用户登录到 CakePHP 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15124894/
SELECT *, `o_cheque_request.member_id`, `o_cheque_request.wallet_id` FROM `o_cheque_request`, `o_mem
根据某一条件从数据库表中查询 『有』与『没有』,只有两种状态,那为什么在写SQL的时候,还要**SELECT count(*)**呢? 无论是刚入道的程序员新星,还是精湛沙场多年的程序员老白,都是一如
我试图找出一个文件是否存在,如果存在,验证css样式是否已经存在,如果不存在,将它们写在文件末尾... 我已经完成了这一切,但分 3 个步骤: 该文件是否存在? FileInfo fi= new Fi
我们正在开发即时消息传递应用程序,并且需要在用户的化身上用绿点显示用户 friend 的“状态”。 “状态”远远超出了“my_app_is_opened_and_on_focus”,这意味着(我猜可能
模式 Movie(title, year, director, budget, earnings) Actor(stagename, realname, birthyear) ActedIn(stag
我有一个正在尝试创建的 MySQL 触发器,但无法获得正确的语法。 触发器应该遍历一组关键字并将其与插入数据库的新帖子的标题进行匹配。如果找到匹配项,它应该将新帖子分配给该存储桶并更新存储桶的关键字集
我有 3 个表......用户、更新和碰撞。 我想向发出 api 请求的用户返回最新订单的 feed 更新,并提供显示 feed 中每个状态所需的所有数据。我还需要包括更新是否已被发出 api 请求的
我正在尝试呈现一个带有 UIView 的 UIViewController。 以下是我在 viewDidLoad 方法中尝试的代码。 //create the view controller UIVi
我正在努力弄清楚如何在不对 mysql 进行两次调用的情况下从一个表中检查两件事。 我有一个 Members 表。我想测试MemberID 列中是否存在某个值,以及PhoneNumber 列中是否存在
以下代码给出了一个没有 Do Compile 错误的循环: Loop Sheets("Snap").Rows(1).AutoFilter Field:=5, Criteria1:=List
是否可以通过检查“dig”的输出来检查域名的存在? 在绑定(bind)源中,我发现了这些常量: 0 DNS_R_NOEROR 1 DNS_R_FORMERR 2 DNS_R_SERVFAIL 3 DN
Controller 有问题 我在 Windows 上使用服务器,一切正常,但在互联网上我试图访问页面 social_apartament/beauty_life/并且找不到该页面,代码错误 404这
/** This is struct S. */ struct S(T) { static if(isFloatingPoint!T) { /// This version works
JVM 类型删除如何帮助 Clojure?没有它,Clojure 还能存在吗?如果 JVM 有具体化的类型会发生什么?也就是说,Clojure 将如何改变? 最佳答案 Clojure 根本不会有太大变
许多论文等提到对“system()”的调用是不安全且不可移植的。我不反对他们的论点。 不过,我注意到许多 Unix 实用程序都有一个等效的 C 库。如果没有,源可用于各种这些工具。 虽然许多论文和此类
在我的 Node js 应用程序中,我有一个用户登录 api。上面我在服务器端代码中创建了一个名为 customerid 的变量。现在,当用户身份验证成功时。我将他的 userid 值存储在我的 cu
我有一个工作资源管理器组,由 Ubuntu 14.04 虚拟机、网络接口(interface)、公共(public) IP 地址和存储帐户组成。我已经从这组资源中创建了一个模板。 当我尝试部署这组资源
我有一个函数createminor4(arr,锦标赛)它基本上将arr分成4组,每组8人,然后将它们一次交换到tourney 1组。从那里它插入四个{},其中有 4 个带有空数组的键。 我已经在 Ch
我有一个图表,其中有两个图例。我需要更改其中一个图例的点的大小。 我需要更改图例中“市场类型”的项目符号大小。我使用示例 here但不适用于我的图表。 我的代码如下: k <- ggplot(subs
我有 fiddle here展示我正在尝试做的事情。 我有一个动态生成的表,因此列可以按用户选择的任何顺序显示。因此,我尝试获取两个特定 header 的索引,以便可以将 CSS 类添加到这两列以供稍
我是一名优秀的程序员,十分优秀!