我试图通过自编代码模拟Facebook登录工作流程(即不使用Facebook PHP SDK),根据Facebook文档,这应该是可能的并且非常简单:
“使用我们的SDK的应用程序可以检查是否有人已使用内置函数登录 . 当一个人登录时,所有其他应用程序必须创建自己的存储方式“
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2
我的主要动机是Facebook和SDK的频繁更改令人沮丧,并敦促我使用自编写的库迁移到本机HTTP请求 .
使用SDK时,进程应该是(这是以前的版本):
$facebook = new Facebook(array(
'appId' => MY_APP_ID,
'secret' => MY_APP_SECRET,
));
$this_user_facebook_id = $facebook->getUser(); // Get User ID
if($this_user_facebook_id > '0')
{
try
{
$user_access_token = $facebook->getAccessToken();
// do whatever you like
}
}
catch(FacebookApiException $e)
{
print_r($e);
$this_user_facebook_id = NULL;
}
我想要遵循的过程是:
-
刮取重定向URL - 如果它包含"code=..." $ _GET变量,则表示用户已登录,我可以查询access_token . 否则,提供Facebook登录链接
问题是我在这个阶段被放弃了:我试图阅读Facebook重定向 Headers ,直到意识到Facebook实际上使用元标记重定向用户:
<meta http-equiv="refresh" content="0;url=https://www.facebook.com/login.php?skip_api_login=1&api_key=............ ------LONG FACEBOOK URL ------->
问题是我在那里找不到原生URL,即即使用户 does get 重定向到 http://MY_APP_REDIRECT_URL/?code=
,代码= ....变量也会丢失
我试图读取CURL Headers ,但那里什么都没有 . 我还尝试生成APP访问令牌并通过它查询用户访问令牌(失败) .
有线索吗?任何想法如何生成本机HTTP图谱API请求,导致查询用户access_token?我有三天在网上试图解决这个问题,Facebook文档也没那么有用 .
1 回答
实际上链接到
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#token
所以他们说这是因为他们用于例如JS SDK,会话已经由Facebook存储,因此获取登录状态可以动态完成,而不是手动方式 .
我看到你也在使用旧的PHP SDK
$this_user_facebook_id = $facebook->getUser();
如果您在源https://github.com/facebookarchive/facebook-php-sdk/blob/master/src/base_facebook.php中检查此功能,您将看到它的作用是检查是否设置了用户,如果没有从可用数据中检查用户 . 此处的可用数据按此顺序排列
任何signed requests
授权码
然后回退到存储用户的任何持久存储 .
如果没有设置,则没有有效用户 .
检查类似通过服务器的最简单方法是为用户存储id和访问令牌(当他们第一次授权应用程序时)
用户通过对话框登录
使用ID /会话(或密码,但您的应用程序有效)存储用户并存储令牌
当下一个应用程序识别出会话时(无论是您设置的cookie管理系统还是简单的用户/传递设置),从数据库中检索令牌并对其进行调试https://developers.facebook.com/docs/graph-api/reference/v2.2/debug_token
4A . 令牌有效吗?是的,不要调用登录对话框
4B . 是令牌invald,Invoke对话框
调试令牌调用的工作原理
https://graph.facebook.com/debug_token?input_token=USER_ACCESS_TOKEN_STORED_IN_DB&access_token=APP_TOKEN
响应
如果令牌无效,则响应中也会返回错误,
is_valid
设置为false .因此,只要您存储从用户检索到的最后一个访问令牌,您就可以判断他是否已经是用户登录到您的应用 .
如果你不存储令牌并且想要确定登录状态,那么这有点复杂 .
您可以在cURL中自动生成的唯一令牌(无需用户交互)是应用程序访问令牌 .
用户互动不仅仅是Facebook的标准 . 它实际上是在OAuth规范中说明的
https://tools.ietf.org/html/rfc6749
Facebook内部为开发人员资源管理器工具和一些本机应用程序生成用户访问令牌,但这取决于Facebook和用户之间的信任 . 由于我们是第三方开发者,Facebook不向开发人员提供那种信任级别 .
现在获取更多技术信息,了解为什么这种情况无法在大规模环境中发挥作用
这就是所有服务器端流程的外观,SDK或无SDK . 第一,第三和第四条腿都可以在后台完成 . 第二站
是什么关注,基本上当用户点击对话框中的按钮时,会发出
POST
请求https://www.facebook.com/v2.2/dialog/oauth/read
从上面可以看出,应该注意的是,要使此POST请求在cURL中工作,您需要
fb_dtsg
用户来防御CSRF攻击,因此您将无法获得此信息 .在对令牌的后续请求中(假设,没有要求其他权限),您将不需要
fb_dtsg
令牌,尽管仍然需要命中此 endpoints 您希望cURL与https://www.facebook.com/dialog/oauth?client_id=MY_APP_ID&redirect_uri=FACEBOOK_REDIRECT_URL&scope=MY_APPROVED_SCOPE
在这里Facebook检查哪个用户正在访问此 endpoints ,唯一的方法是使用有效的cookie
datr
lu
c_user
fr
xs
s
行动
参考:Facebook Ireland Audit Review Report_21 Sept 2012
现在假设您可以获得fb_dtsg和有效的cookie会话数据,使用您的cURL请求,您仍然必须通过发送用户代理来模拟浏览器,因为Facebook会在抓取网站的计算机上进行搜索 .
所以你的cURL请求实际上更符合你的要求
curl 'https://www.facebook.com/v2.2/dialog/oauth/read' -H 'origin: https://www.facebook.com' -H 'accept-encoding: gzip, deflate' -H 'accept-language: en-US,en;q=0.8' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36' -H 'content-type: application/x-www-form-urlencoded' -H 'accept: */*' -H 'referer: https://www.facebook.com/v2.2/dialog/oauth?response_type=code&client_id=819244098116110&redirect_uri=FACEBOOK_REDIRECT_URL' -H 'cookie: datr=...; lu=...; c_user=...; fr=...; xs=...; csm=2; s=...; wd=1408x472; act=...' --data 'fb_dtsg=...&app_id=819244098116110&redirect_uri=FACEBOOK_REDIRECT_URL&display=page&access_token=&sdk=&from_post=1&public_info_nux=1&private=&login=&read=public_profile%2Cbaseline&write=&readwrite=&extended=&social_confirm=&confirm=&seen_scopes=public_profile%2Cbaseline&auth_type=&auth_token=&auth_nonce=&default_audience=&ref=Default&return_format=code&domain=&sso_device=&sheet_name=initial&__CONFIRM__=1&__user=13608786&__a=1&__dyn=...&__req=4&ttstamp=...&__rev=...' --compressed
在此之后,您将得到响应
for (;;);{"__ar":1,"payload":null,"jsmods":{"require":[["ServerRedirect","redirectPageTo",[],["https:FACEBOOK_REDIRECT_URL?code=CODE_PARAM#_=_",true]]]},"js":["J93Wm"],"bootloadable":{},"resource_map":{"J93Wm":{"type":"js","crossOrigin":1,"src":"https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yg\/r\/IZE34GLft38.js"}},"ixData":{},"lid":"0"}
所以是的浏览器模拟是棘手的,并且取决于许多因素和信任级别,大多数用户将无法提供给您,因为基本上所有这些都可以工作,您需要用户的密码 .
所有上述情况都不言而喻,这只是理论工作,展示了如何在没有用户启动流程的情况下进行 . 正如之前在评论中所提到的,这既反对Facebook TOS和Facebook开发者政策,所以我认为危及您的开发者帐户,个人帐户,应用程序和客户的风险超过了不必处理用户交互的好处 .
也许尝试发送拉取请求来更新PHP SDK到您喜欢的? https://github.com/facebook/facebook-php-sdk-v4/pulls :)