我认为如果我们使用REST或Graph API调用Facebook,我们会知道它是否是假的,因为它会回来说假session / auth_token / access_token。但是,如果我们显示自己的数据库信息,例如用户的“最喜欢的产品列表”,那么我们不会对Facebook进行任何调用,而是显示我们的数据库数据。我们怎么知道它真的是用户,而不是伪造cookie的人?
答案 0 :(得分:2)
当你用facebook阅读cookie时,它包含一个名为'sig'的值。使用此值,其他cookie值以及您的应用程序密钥,您可以散列cookie的内容并根据sig对其进行验证。如果匹配,则cookie有效。您可以信任此结果,因为只有您和Facebook才能访问应用程序机密。以下是Facebook的PHP SDK如何实现它的示例。任何受人尊敬的Facebook SDK都会在内部为您完成这一切。
/**
* Validates a session_version=3 style session object.
*
* @param Array $session the session object
* @return Array the session object if it validates, null otherwise
*/
protected function validateSessionObject($session) {
// make sure some essential fields exist
if (is_array($session) &&
isset($session['uid']) &&
isset($session['access_token']) &&
isset($session['sig'])) {
// validate the signature
$session_without_sig = $session;
unset($session_without_sig['sig']);
$expected_sig = self::generateSignature(
$session_without_sig,
$this->getApiSecret()
);
if ($session['sig'] != $expected_sig) {
self::errorLog('Got invalid session signature in cookie.');
$session = null;
}
// check expiry time
} else {
$session = null;
}
return $session;
}
C#(Facebook C# SDK)中的内容相同:
/// <summary>
/// Validates a session_version=3 style session object.
/// </summary>
/// <param name="session">The session to validate.</param>
protected override void ValidateSessionObject(FacebookSession session)
{
if (session == null)
{
return;
}
var signature = this.GenerateSignature(session);
if (session.Signature == signature.ToString())
{
return;
}
session = null;
}
/// <summary>
/// Generates a MD5 signature for the facebook session.
/// </summary>
/// <param name="session">The session to generate a signature.</param>
/// <returns>An MD5 signature.</returns>
/// <exception cref="System.ArgumentNullException">If the session is null.</exception>
/// <exception cref="System.InvalidOperationException">If there is a problem generating the hash.</exception>
protected override string GenerateSignature(FacebookSession session)
{
var args = session.Dictionary;
StringBuilder payload = new StringBuilder();
var parts = (from a in args
orderby a.Key
where a.Key != "sig"
select string.Format(CultureInfo.InvariantCulture, "{0}={1}", a.Key, a.Value)).ToList();
parts.ForEach((s) => { payload.Append(s); });
payload.Append(this.ApiSecret);
byte[] hash = null;
using (var md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create())
{
if (md5 != null)
{
hash = md5.ComputeHash(Encoding.UTF8.GetBytes(payload.ToString()));
}
}
if (hash == null)
{
throw new InvalidOperationException("Hash is not valid.");
}
StringBuilder signature = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
signature.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));
}
return signature.ToString();
}
答案 1 :(得分:0)
唯一值得信赖的是旧版REST api的session_key
和Graph API的access_token
。获得它后,将其传递给服务器端并提供数据后备请求。在服务器端调用facebook api并获取当前用户ID。获得用户ID后,您可以将其存储在会话中并稍后使用。
答案 2 :(得分:-1)
不要将其存储在cookie中。把它放在一个会话变量中,这样你就有了控制权
答案 3 :(得分:-1)
不要将用户ID放在cookie中。会话cookie应该只是一个随机数,映射到服务器端会话数据库中的记录。与该会话关联的任何数据仅存储在服务器端。
这样,为了伪造会话,攻击者必须猜测当时实际使用的随机数。鉴于有很多随机数和会话到期,这几乎是不可能的。
答案 4 :(得分:-1)
这里有一些方法。
效率低下:每当执行经过身份验证的操作时,抓取FB cookie并使用其中的数据进行虚拟API调用,以查看访问令牌是否有效并与用户匹配(即抓取/我?fields = id)
更高效:第一次看到用户的FB cookie时,将该cookie存储在用户的服务器端会话中(在cookie中将足够难以猜测的会话ID传递给客户端)
另一种方法,并且不需要服务器端会话状态:第一次看到用户的FB cookie时,HMAC使用只有您的服务器具有的秘密,并将生成的哈希存储在cookie中。然后你可以检查FB cookie是否有有效散列,如果有,你就相信它。否则,您将回到验证阶段。