首页 文章

检查Facebook用户是否在没有PHP SDK的情况下登录

提问于
浏览
1

我试图通过自编代码模拟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;
    }

我想要遵循的过程是:

问题是我在这个阶段被放弃了:我试图阅读Facebook重定向 Headers ,直到意识到Facebook实际上使用元标记重定向用户:

<meta http-equiv="refresh" content="0;url=https://www.facebook.com/login.php?skip_api_login=1&amp;api_key=............ ------LONG FACEBOOK URL ------->

问题是我在那里找不到原生URL,即即使用户 does get 重定向到 http://MY_APP_REDIRECT_URL/?code= ,代码= ....变量也会丢失

我试图读取CURL Headers ,但那里什么都没有 . 我还尝试生成APP访问令牌并通过它查询用户访问令牌(失败) .

有线索吗?任何想法如何生成本机HTTP图谱API请求,导致查询用户access_token?我有三天在网上试图解决这个问题,Facebook文档也没那么有用 .

1 回答

  • 3

    “使用我们的SDK的应用程序可以检查是否有人已使用内置函数登录 . 当一个人登录时,所有其他应用程序必须创建自己的存储方式“

    实际上链接到

    https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#token

    存储访问令牌和登录状态在此流程中,您已经有人通过身份验证并登录 . 您的应用已准备好代表他们进行API调用 . 在此之前,它应该使用应用程序存储访问令牌和人员的登录状态 . 存储访问令牌在您的应用程序收到上一步中的访问令牌后,应该存储令牌,以便在进行API调用时,该应用程序的所有部分都可以使用该令牌 . 这里没有具体的过程,但一般情况下,如果您正在构建Web应用程序,最好将令牌添加为会话变量,以识别与特定人员的浏览器会话,如果您正在构建本机桌面或移动设备应用程序,然后您应该使用您的应用程序可用的数据存储区 . 此外,应用程序应将令牌与user_id一起存储在数据库中以识别它 . 请参阅我们关于访问令牌文档中访问令牌大小的说明 . 跟踪登录状态同样,您的应用程序应存储一个人的登录状态,这有助于避免必须对“登录”对话框进行其他调用 . 无论您选择何种程序,请修改您的登录状态检查以对其进行说明 .

    所以他们说这是因为他们用于例如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

    响应

    {
      "data": {
        "app_id": "APP_ID", 
        "application": "APP_NAME", 
        "expires_at": 1422295200, 
        "is_valid": true, 
        "scopes": [
          "public_profile", 
          "read_mailbox", 
          "read_page_mailboxes", 
          "ads_management", 
          "ads_read", 
          "manage_pages", 
          "publish_actions"
        ], 
        "user_id": "USER_ID"
      }
    }
    

    如果令牌无效,则响应中也会返回错误, is_valid 设置为false .

    {
      "data": {
        "app_id": "APP_ID", 
        "application": "AnyLeepingTest", 
        "error": {
          "code": 190, 
          "message": "Error validating access token: Session has expired on Jan 9, 2015 7:00pm. The current time is Jan 26, 2015 8:22am.", 
          "subcode": 463
        }, 
        "expires_at": 1420858800, 
        "is_valid": false, 
        "profile_id": "PROFILE_ID", 
        "scopes": [
          "public_profile", 
          "read_mailbox", 
          "read_page_mailboxes", 
          "ads_management", 
          "ads_read", 
          "manage_pages", 
          "publish_actions"
        ], 
        "user_id": "USER_ID"
      }
    }
    

    因此,只要您存储从用户检索到的最后一个访问令牌,您就可以判断他是否已经是用户登录到您的应用 .


    如果你不存储令牌并且想要确定登录状态,那么这有点复杂 .

    您可以在cURL中自动生成的唯一令牌(无需用户交互)是应用程序访问令牌 .

    用户互动不仅仅是Facebook的标准 . 它实际上是在OAuth规范中说明的

    https://tools.ietf.org/html/rfc6749

    在启动协议之前,客户端向授权服务器注册 . 客户端向授权服务器注册的方法超出了本规范的范围,但通常涉及最终用户与HTML注册表单的交互 .

    Facebook内部为开发人员资源管理器工具和一些本机应用程序生成用户访问令牌,但这取决于Facebook和用户之间的信任 . 由于我们是第三方开发者,Facebook不向开发人员提供那种信任级别 .

    现在获取更多技术信息,了解为什么这种情况无法在大规模环境中发挥作用

    Server Flow

    这就是所有服务器端流程的外观,SDK或无SDK . 第一,第三和第四条腿都可以在后台完成 . 第二站

    用户接受对话框并发送到redirect_uri并包含代码参数

    是什么关注,基本上当用户点击对话框中的按钮时,会发出 POST 请求

    https://www.facebook.com/v2.2/dialog/oauth/read

    fb_dtsg:FB_DTSG
    app_id:APP_ID
    redirect_uri:https://developers.facebook.com/tools/explorer/callback
    display:page
    access_token:
    sdk:
    from_post:1
    public_info_nux:1
    private:
    login:
    read:public_profile,baseline
    write:
    readwrite:
    extended:
    social_confirm:
    confirm:
    seen_scopes:public_profile,baseline
    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:...
    

    从上面可以看出,应该注意的是,要使此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 :)

相关问题