我有一个用PHP编写的网站,并且正在使用Python和Django添加新功能。其中一部分将使用标准的contribs.auth包进行Django认证。我正在使用Django用户认证与PHP。这个基于cookie的认证方案是安全的吗?
一旦有人使用我们的Django设置登录,当他们来到PHP端时,我需要看到他们已经登录并使用数据库中的用户信息)。
使用此Django sessionid cookie值,获取用户标识和证明Django会话标识从PHP有效的最佳方式是什么?
我的计划是在登录时对Django会话ID,我的Django密钥和用户ID进行散列。该值将被设置为额外的cookie。然后在PHP中,我将提取用户标识,对其进行散列和秘密密钥以及Django sessionid cookie值,并比较它们是否匹配。
我扩展了身份验证登录视图,以在用户成功通过身份验证后设置额外的cookie。它将返回HttpResponseSetAuthCookieAndRedirect而不是HttpResponseRedirect。
HttpResponseSetAuthCookieAndRedirect获取request.session.session_id和user_id作为参数。
class HttpResponseSetAuthCookieAndRedirect(HttpResponse):
""" a cookie enhanced version of HttpResponseRedirect """
status_code = 302
def __init__(self, user_id, session_id, redirect_to):
HttpResponse.__init__(self)
self['Location'] = iri_to_uri(redirect_to)
my_hash=hashlib.sha512('{0}|-|{1}|-|{2}'.format(settings.SECRET_KEY,user_id,session_id)).hexdigest()
cookie_hash="{0}::{1}".format(user_id,my_hash[:64])
self.set_cookie('check', value=cookie_hash, max_age=172800, path='/', domain=None)
此设置一个cookie是会话ID的散列,我的Django的密钥,并且该会话ID匹配的认证用户ID。
在PHP中,
$check_cookie=$_COOKIE['check'];
$django_cookie=$_COOKIE['sessionid'];
$check_cookie=str_replace('"','',$check_cookie);
$django_cookie=str_replace('"','',$django_cookie); //they have quotes for some reason
$parts=explode('::',$check_cookie);
$sent_user_id=(int)$parts[0];
$sent_hash=$parts[1];
$cookie_hash=hash('sha512',"$secret_key|-|$sent_user_id|-|$dj_cookie_sessionid");
$reconstructed_security_hash=$sent_user_id.'::'.substr($cookie_hash,0,64);
if($reconstructed_security_hash==$cookie_hash)
{
return $sent_user_id; //cookies are valid, and user id is the one set by Django for this session id.
}
return false; //cookies do not match
这是工作至今。
这种想法听起来不错?
顺便说一下,我对Django略微陌生,所以如果有一些更好的方法来做到这一点(比如通过sessionid值查找存储在数据库中的会话),我愿意接受建议。 – Cole 2011-01-28 11:34:42