2011-01-28 47 views
3

我有一个用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 

这是工作至今。

这种想法听起来不错?

+0

顺便说一下,我对Django略微陌生,所以如果有一些更好的方法来做到这一点(比如通过sessionid值查找存储在数据库中的会话),我愿意接受建议。 – Cole 2011-01-28 11:34:42

回答

3

如果您可以在PHP中取消选择什么Django进入会话,那么您可以直接从数据库中获取相关会话数据(使用来自cookie的会话ID),然后您将拥有一个直接信息,在Django站点 - 如果有的话。

编辑:

这里的 “加密” Django使用:

http://code.djangoproject.com/browser/django/tags/releases/1.2.4/django/contrib/sessions/backends/base.py#L86

“解密” 你应该得到的东西像后:

{ 
    '_auth_user_id': 123, 
    '_auth_user_backend': 'django.contrib.auth.backends.ModelBackend', 
} 

- 加当然其他的你自己设定的会话数据

+0

听起来不错,然后我可以使用会话存储,而这可能会少一些工作。你知道会话数据是否只是腌制?它看起来也是Base64编码的。 Django文档说会话数据是'加密的'... – Cole 2011-01-28 14:43:21

+0

看看我上面添加的链接。 – 2011-01-28 19:12:38

0

你知道是否有可能构建一种解决方案,也就是说,可以登录到PHP应用程序并使用此登录信息登录到Django应用程序,而无需再次键入用户名/密码?