Django单点登录和Php站点:跨域登录?

时间:2009-07-19 21:35:50

标签: php django login authentication

我正在django中构建一个小应用程序作为服务,现在是时候将它集成到一些客户端PHP Web应用程序上。

来自域名www.a.com的客户 A 会为其用户处理自己的身份验证,并可能会使用Cookie进行会话。

我如何从他的域中登录用户也登录我的Django应用程序dommain www.b.com/clientA/?

我知道如何让我们在我的域上重新登录并使用域名A的authbackend检查凭据,但这意味着用户必须输入他的登录/通行证两次:www.a.com和www.b.com

出于安全考虑,我认为无法从域名www.a.com访问cookie。

你会如何处理?

4 个答案:

答案 0 :(得分:7)

您认为无法访问来自其他域的Cookie是正确的。但是,如果它位于子域中,则应该能够在正确设置cookie时访问它们。

如果你绝对必须在完全独立的域上拥有它们,那将会有点棘手。如果你不能修改现有的PHP代码,你几乎可以忘记它。

一种选择是使用OpenID - 这可能是解决这个问题的最简单方法,因为有可用于PHP和Python的OpenID库。 OpenID允许你像真实一样进行单点登录,并且由于它已经在各种站点上使用,因此它已被证明并且有效。

另一种选择是编写自定义单点登录系统。

基本思路是,当用户到达您的站点时,您将他们引导到登录站点。这可以是PHP或Python的结尾,也可以是单独的。在这里,用户将登录,然后登录生成一个密钥 - 这可以是一个哈希,随机字符串,只要它是不可预测的 - 然后用密钥将用户重定向回主站点。 p>

然后主站点看到用户有一个密钥,并在后台向登录站点发送请求以验证用户的密钥。

现在用户已在一个站点登录。当用户访问第二个站点时,它也会将用户重定向到登录站点。由于用户已经登录,登录站点只是使用新的密钥重定向用户,第二个站点从登录站点验证它,现在用户登录而无需再次输入凭据。

答案 1 :(得分:6)

好的,这是如何从PHP验证Django用户,或如何从PHP“读取”Django密码。

我认为OpenID是最好的解决方案,但我必须在今天共享相同数据库的PHP应用程序中验证Django用户,这就是我解决的问题:

<?php

/* Generates crypted hash the same way as Django does */
function get_hexdigest($algorithm, $salt, $raw_password) {
   if (!array_in($algorithm, array('md5', 'sha1'))) {
       return false;
   }
   return $algorithm($salt.$raw_password);
}

/* Checks if password matches the same way Django does */
function check_password($raw_password, $django_password) {
    list($algorithm, $salt, $hsh) = explode('$', $django_password);
    return get_hexdigest($algoritm, $salt, $raw_password) === $hsh;
}

?>

关键是要了解Django保存密码的格式,即:

[算法] $ [盐] $ [散列]

例如,我有一个“admin”用户,密码为“admin”,auth_user行中的密码字段为:

sha1$63a11$85a93f217a72212b23fb0d5b95f3856db9575c1a

算法为“sha1”,随机生成的盐为“63a11”,加密的散列为“85a93f217a72212b23fb0d5b95f3856db9575c1a”。

那么你是谁在PHP中生成加密的哈希?您可以简单地连接salt和原始密码,并将其与算法一起散列,在本例中为sha1:

<?php 

$salt = '63a11';
$pass = 'admin';

echo sha1($salt.$admin); // prints "85a93f217a72212b23fb0d5b95f3856db9575c1a"

?>

这并不困难!我通过阅读Django源代码中的相关代码得到了它。

答案 2 :(得分:1)

您可以来回使用HTTP重定向。当用户访问www.b.com并且未设置cookie时,重定向到www.a.com/crosslogin?return_to=URL&challenge=stuff。在a.com上,检查cookie,如果已设置,则重定向到URL?verified=otherstuff

如果您希望用户防止伪造身份验证,则需要质询 - 响应加密。 a.com和b.com需要设置共享密钥,并使用该秘密加密内容。 otherstuff也用这个秘密加密;当解密时,它给出一个元组(东西,用户)。 b.com可能需要保留重播缓存以确保其他缓存只能使用一次。

答案 3 :(得分:0)

我看到以下选项:

1)使用Open ID,Jani Hartkainen建议。这可能是最好的解决方案。

2)通过http反向代理使用一个域:

使用反向http代理将php应用程序和django应用程序放在同一个域中。这样您就可以访问php应用程序的会话cookie。

在django应用程序中获取php会话ID后,运行对PHP应用程序的请求,并设置会话cookie以检查谁登录。 不幸的是,这可能需要html抓取或在PHP应用程序中实现一个简单的服务,该服务将返回登录用户的名称。 获得登录用户后,您可以在django应用程序中对其进行授权。

3)通过GET传递PHP会话ID:

修改PHP应用程序,将会话ID添加为指向django应用程序链接的参数。 例如,要求客户引用您的网站,如下所示:

<yourwebsite.com>/?client_session_id=<session_id>&client_name=<client_name>

获得会话ID后,您可以按照第2点中的说明对用户进行身份验证。