我们的客户A来自www.a.com域,处理他自己用户的身份验证,并且可能使用cookie进行会话管理。
如何使来自他域名的已登录用户也可以在我的Django应用程序www.b.com/clientA/上登录?
我知道我可以让他们在我的域名上重新登录,并使用一个authbackend检查A域的凭据,但这意味着用户必须在www.a.com和www.b.com上输入他的登录/密码两次。
由于安全原因,无法从www.a.com域访问cookie。
你会如何处理这个问题?
好的,这是如何从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中如何生成加密后的哈希值呢?只需将盐值和原始密码连接起来,并使用该算法进行哈希运算即可,例如本例中使用的是sha1算法:
<?php
$salt = '63a11';
$pass = 'admin';
echo sha1($salt.$pass); // prints "85a93f217a72212b23fb0d5b95f3856db9575c1a"
?>
您可以使用 HTTP 重定向来回传递。当用户访问 www.b.com 且没有设置 cookie 时,重定向到 www.a.com/crosslogin?return_to=URL&challenge=stuff
。在 a.com 上,检查 cookie 是否已设置,如果已设置,则重定向到 URL?verified=otherstuff
。
如果您想要防止用户伪造身份验证,则需要挑战-响应加密。a.com 和 b.com 需要设置共享密钥,并使用该密钥加密 stuff。otherstuff 也使用该密钥加密;解密后,它会给出一个元组 (stuff, user)。b.com 可能需要保留重放缓存以确保 otherstuff 只能使用一次。
我看到以下选项:
1)像Jani Hartkainen建议的那样使用Open ID。这可能是最好的解决方案。
2)通过http反向代理使用一个域:
使用反向http代理将php应用程序和django应用程序放在同一个域中。这将使您可以访问您的php应用程序的会话cookie。
一旦您在django应用程序中获取了php会话ID,请使用设置为会话cookie的请求运行对PHP应用程序的请求,以检查谁已登录。 不幸的是,这可能需要HTML抓取或在PHP应用程序中实现一个简单的服务,该服务将返回已登录用户的名称。 一旦您获得了已登录的用户,就可以在django应用程序中对其进行授权。
3)通过GET传递PHP会话ID:
修改PHP应用程序,将会话ID作为参数添加到指向您的django应用程序的链接中。 例如,要求客户按以下方式引用您的网站:
<yourwebsite.com>/?client_session_id=<session_id>&client_name=<client_name>