• Facebook “Like” 与否判断



    用例:

    在开发facebook应用的过程当中,经常要判断facebook用户对当前应用的“Like”状态,从而显示不同的内容。

    一个典型的例子是在表单上放上一个遮罩层(通常是一个id为shade的div),用户无法透过遮罩层点击输入框,从而诱导用户点击facebook菜单上的 “Like”按钮,页面进行一次跳转,在跳转的过程当中,我们可以从facebook返回的信息当中获得“Like”的状态,进而判断是否取消显示遮罩层。

    总体思想:

    在嵌入facebook的应用前端页面,加入以下代码(加在body的closing tag之前):

    <div id="fb-root"></div>
    <script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
    <script type="text/javascript">
    FB.init({
    appId: [facebook_app_id],
    // 注意替换相应的facebook app id
    status: true,
    cookie:
    true,
    xfbml:
    true,
    oauth:
    true
    });
    FB.Canvas.setAutoResize(
    10); // 这句调用facebook api来调整嵌入的窗口大小,不是必要的但一般最好加上
    </script>

    之后,每当刷新facebook应用页面的时候,facebook都会在request里加上一个叫做“signed_request”的parameter,它是由一个“点”符号连接起来的两个乱码字符串,看起来像这样(注意“点”前后没有空格,这边加上空格只是方便阅读):

    vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso .  eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0
    

    前半部分是一个HMAC SHA-256加密的字符串, 后半部分是一个base64url编码的JSON object.

    后台实现:

    通过将后半部分通过密钥(facebook application secret)加密,将得出的字符串与前半部分进行比较,如果相同则后半部分所包含的JSON object是有效的,进而将后半部分进行base64url解码,得出真正的JSON object。JSON object中一定有一个名为“like”的键,如果其值不为空的话,说明用户已经点击过“Like”按钮了。注意:键值在不同语言中不同,“liked”(c#)或 “1”(php),具体代码示例如下:

    PHP:

    <?php
    $application_secret = [facebook_application_secret]; // 注意替换相应的facebook application secret
    function parse_signed_request($signed_request, $secret) {
    list($encoded_sig, $payload) = explode('.', $signed_request, 2);

    // decode the data
    $sig = base64_url_decode($encoded_sig);
    $data = json_decode(base64_url_decode($payload), true);

    if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
    error_log('Unknown algorithm. Expected HMAC-SHA256');
    return null;
    }

    // check sig
    $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
    if ($sig !== $expected_sig) {
    error_log('Bad Signed JSON signature!');
    return null;
    }
    return $data;
    }

    function base64_url_decode($input) {
    return base64_decode(strtr($input, '-_', '+/'));
    }
    ?>

    $payloadArray = parse_signed_request($_REQUEST["signed_request"], $application_secret);
    <div id="shade" style="<?php
    if($payloadArray["page"]["liked"] == "1") echo "display:none;"; // 取消遮罩层
    else echo "display:block;"; // 显示遮罩层
    ?>"> <div id="like-enter"><span>Like us to enter the competition</span></div>
    </div>

    C#:

    private static string APPLICATION_SECRET = [facebook_application_secret]; // 注意替换相应的facebook application secret

    protected void Page_Load(object sender, EventArgs e)
    {
    if (Request.Params["signed_request"] != null)
    {
    string decodedPayloadString = ValidateSignedRequest(Request.Params["signed_request"]);
    string[] payloadArray = decodedPayloadString.Split(',');
    string liked = payloadArray[3];
    string likeValue = liked.Substring(7, 5);

    if (likeValue == ":true")
    {
    div_shade.Visible = false; // 取消遮罩层
    }
    else
    {
    div_shade.Visible = true; // 显示遮罩层
    }

    }
    }

    private string ValidateSignedRequest( string signedRequest ) {
    string[] signedRequestArray = signedRequest.Split( '.' );
    string expectedSignature = signedRequestArray[0];
    string payload = signedRequestArray[signedRequestArray.Length - 1];

    byte[] Hmac = SignWithHmac( UTF8Encoding.UTF8.GetBytes( payload ), UTF8Encoding.UTF8.GetBytes( LikeDetection.APPLICATION_SECRET ) );
    string HmacBase64 = ToUrlBase64String( Hmac );

    bool result = (HmacBase64 == expectedSignature);
    if (result)
    {
    string decodedPayload = System.Text.UTF8Encoding.UTF8.GetString( FromBase64ForUrlString( payload ) );
    }

    return decodedPayload;
    }

    private byte[] SignWithHmac( byte[] dataToSign, byte[] keyBody ) {
    using ( System.Security.Cryptography.HMACSHA256 hmacAlgorithm = new System.Security.Cryptography.HMACSHA256( keyBody ) ) {
    hmacAlgorithm.ComputeHash( dataToSign );
    return hmacAlgorithm.Hash;
    }
    }

    private string ToUrlBase64String( byte[] Input ) {
    return Convert.ToBase64String( Input ).Replace( "=", String.Empty ).Replace( '+', '-' ).Replace( '/', '_' );
    }

    private byte[] FromBase64ForUrlString( string base64ForUrlInput ) {
    int padChars = ( base64ForUrlInput.Length % 4 ) == 0 ? 0 : ( 4 - ( base64ForUrlInput.Length % 4 ) );

    StringBuilder result = new StringBuilder( base64ForUrlInput, base64ForUrlInput.Length + padChars );
    result.Append( String.Empty.PadRight( padChars, '=' ) ).Replace( '-', '+' ).Replace( '_', '/' );

    return Convert.FromBase64String( result.ToString() );
    }

    还值得注意的很重要一点是:通过以上方法获取的“Like”的值,只有在加载facebook应用的home page的时候,也就是说,只有在facebook outer frame刷新的时候才能获取到,如果在facebook内嵌的我们自行搭建的iframe内进行跳转,这个值是无法被再次获取得到的,因此如果想要之后 得到“Like”的状态,就必须用到Cookie或Session或通过URL传值的方法保留这个信息。

  • 相关阅读:
    3.25训练题
    hdu1495
    poj1426 宽搜
    高斯消元
    codeforces 999E 强联通分量
    hdu4289城市与歹徒 网络流
    蒟蒻的离散化模板
    樱花,素数筛
    【转】分圆问题:一个诡异的数列规律
    hdu1257最少拦截系统 贪心
  • 原文地址:https://www.cnblogs.com/booth/p/2268678.html
Copyright © 2020-2023  润新知