这个PHP cookie解析片段的C#等价物是什么?

时间:2010-07-27 02:55:06

标签: c# php cookies

我正在尝试将这个PHP cookie解析片段转换为C#,但我的PHP有点生疏。它取自facebook SDK sample

<?php

define('FACEBOOK_APP_ID', 'your application id');
define('FACEBOOK_SECRET', 'your application secret');

function get_facebook_cookie($app_id, $application_secret) {
    $args = array();
    parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);
    ksort($args);
    $payload = '';
    foreach ($args as $key => $value) {
        if ($key != 'sig') {
            $payload .= $key . '=' . $value;
        }
    }
    if (md5($payload . $application_secret) != $args['sig']) {
      return null;
    }
    return $args;
}

$cookie = get_facebook_cookie(FACEBOOK_APP_ID, FACEBOOK_SECRET);
echo 'The ID of the current user is ' . $cookie['uid'];

?>

这是我到目前为止所做的,但它不太正确:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    HttpCookie cookie = GetCookie();
    IsLoggedIn = cookie != null;
}

private HttpCookie GetCookie()
{
    // based on the php example at http://developers.facebook.com/docs/authentication/
    HttpCookie cookie = Request.Cookies["fbs_" + FacebookClientId];
    StringBuilder payload = new StringBuilder();
    if (cookie != null)
    {
        foreach (string key in cookie.Values.Keys)
        {
            if (key != "sig")
            {
                payload.Append(key + "=" + cookie.Values[key]);
            }
        }

        string sig = cookie.Values["sig"];

        if (sig == GetMD5Hash(payload.ToString()))
        {
            return cookie;
        }
    }

    return null;
}

public string GetMD5Hash(string input)
{
    MD5CryptoServiceProvider cryptoServiceProvider = new MD5CryptoServiceProvider();
    byte[] bytes = Encoding.UTF8.GetBytes(input);
    bytes = cryptoServiceProvider.ComputeHash(bytes);
    StringBuilder s = new StringBuilder();

    foreach (byte b in bytes)
    {
        s.Append(b.ToString("x2").ToLower());
    }

    return s.ToString();
}

我不确定的一部分是parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);。从我可以告诉它从修剪的cookie值创建一个数组。任何人都可以提供一些帮助吗?

2 个答案:

答案 0 :(得分:2)

如果我正确阅读:

trim($_COOKIE['fbs_' . $app_id], '\\"')

将从名为\的cookie中存储的值的开头和结尾修剪"fbs_FACEBOOK_APP_ID(双反斜杠在单引号字符串中转义反斜杠并且可以告诉修剪从字符串中修剪哪些字符。)

同时,parse_str然后将其解析为关联数组,就好像它是一个查询字符串一样。所以,我假设该cookie的值应该看起来像一个查询字符串。

希望这有帮助。

答案 1 :(得分:1)

我的原始C#版本存在一些问题。

  • 我忘了在Facebook MD5哈希中包含FacebookSecret作为salt。
  • 需要修剪cookie.Value并将其解析为查询字符串,如George Marian和Alex JL所解释。
  • 解析后的Cookie值需要为UrlDecoded。我想ASP.NET Url会在创建Cookie对象时对它们进行编码。
  • 默认编码应该用于创建哈希,而不是UTF8。

这是工作解决方案:

private HttpCookie GetCookie()
{
    // based on the php example at http://developers.facebook.com/docs/guides/canvas/#canvas
    HttpCookie cookie = Request.Cookies["fbs_" + FacebookClientId];
    if (cookie != null)
    {
        var pairs = from pair in cookie.Value.Trim('"', '\\').Split('&')
                    let indexOfEquals = pair.IndexOf('=')
                    orderby pair
                    select new
                               {
                                   Key = pair.Substring(0, indexOfEquals).Trim(),
                                   Value = pair.Substring(indexOfEquals + 1).Trim()
                               };

        IDictionary<string, string> cookieValues =
            pairs.ToDictionary(pair => pair.Key, pair => Server.UrlDecode(pair.Value));

        StringBuilder payload = new StringBuilder();
        foreach (KeyValuePair<string, string> pair in cookieValues)
        {
            Response.Write(pair.Key + ": " + pair.Value + "<br/>\n");

            if (pair.Key != "sig")
            {
                payload.Append(pair.Key + "=" + pair.Value);
            }
        }

        string sig = cookieValues["sig"];
        string hash = GetMd5Hash(payload + FacebookSecret);

        if (sig == hash)
        {
            return cookie;
        }
    }

    return null;
}

private static string GetMd5Hash(string input)
{
    MD5CryptoServiceProvider cryptoServiceProvider = new MD5CryptoServiceProvider();
    byte[] bytes = Encoding.Default.GetBytes(input);
    byte[] hash = cryptoServiceProvider.ComputeHash(bytes);

    StringBuilder s = new StringBuilder();
    foreach (byte b in hash)
    {
        s.Append(b.ToString("x2"));
    }

    return s.ToString();
}