如何通过iframe调用验证第三方网站

3
我正在与一所学院合作,需要整合我的课程 - 这样他们的学生可以在学院网站上访问它。我们使用简单的iframe集成。
用户将在学院网站上注册,并将用户信息传递给我,以便我可以启动会话并为他们提供对我的网站上的课程页面的访问权限,通过iframe显示在他们的网站上。
我的网站是基于LAMP构建的,我正在使用ZEND框架。
这是我计划如何做的草图结构:
1)在学院网站上,作为iframe代码的一部分 - 他们将调用我的一个操作类并传递用户电子邮件。
<iframe src="http://mywebsite/user/validate/email/alice@gcc.com"></iframe>

2)现在在用户控制器中,验证操作-我将基本检查用户是否不存在-创建一个新用户或加载具有其电子邮件的现有用户,并启动Zend Auth实例,将用户写入存储并重定向到他的课程页面,如下所示

$currentUser = $userModel->loadUserProfileByEmail($this->_getParam('email'));
$auth = Zend_Auth::getInstance();
$storage = $auth->getStorage();         
$storage->write($currentUser);
return $this->_redirect('/user/my-courses/');

目前我已经完成了这个 - 显然它是有效的

我的问题

1)这是最好的方法吗?我没有用户的密码,因为认证是在学院网站上进行的,他们不希望用户直接登录我的网站。

2)这是一个重要的问题。我有点困惑,关于验证此调用是否由特定的学院发起。我该如何处理 - 他们是否会随着这个 iframe 调用传递一个加密令牌 - 只有我有解密它的密钥 - 我还没有做过这个 - 不知道自己是否让一些简单的事情变得复杂了。

任何建议或意见都将不胜感激 谢谢

2个回答

5

我的建议总结

  • 查看他们是否有联邦身份验证和单点登录(FSSO)解决方案。如果有,使用他们已经有的。
  • 如果没有,建议他们获得FSSO(我推荐Shibboleth),然后使用它。
  • 如果他们不愿意,可以通过模拟Facebook-to-Facebook应用程序交换来自己创建。

细节
在FSSO中,有一个“身份提供者”(IdP)和一个“服务提供者”(SP)。学院是身份提供者,而您是服务提供者。可以有许多服务提供者。只需记住IdP=学院,SP=您。 FSSO的关键点:

  1. 用户通过IdP进行身份验证,而不是SP。
  2. 当IdP信号会话已经过身份验证时,SP会相信它。
  3. 仅当用户在IdP进行身份验证时,SP才会接收到已认证的会话信号。

根据EDUCAUSE的说法, 大多数学院都有FSSO。因此,我的第一个建议是进行调查,找出学院使用的内容。如果他们已经有了FSSO,您的内容将更加安全,代码更简单,您晚上也能睡得更好。幸运的是,我的经验是,学院通常拥有很多东西,但对这些事情的了解并不一定被广播--你必须挖掘一下。

如果他们没有FSSO,我的下一个建议是建议他们安装一个。学习选项,记住单点登录不意味着联合ID -- 你需要两者兼备。

个人而言,我推荐 Shibboleth。它是 开源 的。我曾经在 LAMP 和 ZF1 上使用过它。我知道它有效。使用 Shibboleth,学院将设置一个 Shibboleth IdP,您将 设置您的SP,一起参与身份数据流,一旦用户登录,您将在每个连接上接收环境变量,表示身份验证,如下所示:

array (
    // ...
    [Shib-Application-ID] => my_course_catalog
    [Shib-Session-ID] => _6c45a07c8bc73190242212124221b7
    [Shib-Identity-Provider] => https://shib.college.edu/idp/shibboleth
    [Shib-Authentication-Instant] => 2013-12-31T22:42:07.101Z
    [Shib-AuthnContext-Decl] => urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
    [affiliation] => member@college.edu;staff@college.edu
    [eppn] => XXXXXX@college.edu
    [unscoped-affiliation] => member;staff
    // ...
    [REMOTE_USER] => XXXXXX@college.edu
    // ...
)

我在ZF1中实现的方法是一个控制器插件,用于查找Shib-Session-ID。 如果找到,则制造一个Shibboleth资源,并填充Shib-Session-IDREMOTE_USER,稍后可以查询所需的所有内容。 如果找不到,则重定向到IdP登录页面。(由于您在IFRAME中,不要这样做:而是重定向到“没有内容可显示”/“默认内容”操作。)
如果他们不接受安装FSSO的提案怎么办? 那么你必须自己开发,而你需要解决的瓶颈正如你所指出的那样是信任。
他们给你发送令牌的问题(你的#2个问题)是该令牌可以被拦截(以各种不同的难度程度),并且对你进行重放攻击。 你不能相信你所得到的东西。 你必须接受你所得到的东西,并询问你信任的来源来验证所得到的东西。
更大的问题是,您需要知道浏览网页的用户现在是否是之前已经登录的同一用户。为此,您需要登录cookie,而且您需要检查该cookie当前是否有效。
没有简单的安全方法来执行此操作。这就是为什么FSSO被发明的原因,以便所有这些繁重的工作可以在可靠安全的方式下完成一次。如果您仍然需要自己实现,我可以提供的最佳模型是Facebook应用程序。第三方服务器上运行的“应用程序”可以“看到”已登录的Facebook用户。为了帮助您入门,这里有Facebook应用程序认证教程
目前应用程序身份验证的方式是通过带有登录会话ID的IFRAME POST进行的,您可以通过Facebook进行检查...但我了解到浏览器不再允许这样做,您需要绕过它。 我不确定,但请记住这一点。
从长远来看,FSSO对学院是一笔资产,对您也是一笔福利。 如果可能的话,请选择使用它。 否则,IFRAME第三方应用程序与认证的最新技术是Facebook-to-Facebook应用程序交换,因此请模仿它。 祝你好运!

谢谢 Bishop - 我之前不知道 FSSO,今天学到了新东西 - 我很确定学院不知道 FSSO - 他们正在寻找一种非常快速的集成方法,比如将令牌作为 URL 的一部分从他们那边传递 - 我会在第二天与他们核实 - 感谢您如此详细的回复 - 我会回来发布一些后续问题 - 也会保持这个问题开放,看看是否有其他建议发布 - 感谢您的时间。谢谢 - Gublooo
1
就像你所提到的那样 - 他们对FSSO一无所知,也没有在他们那端实施的专业知识。 - Gublooo

3
我可能误解了你的问题,但我所理解的是你需要:
-一种身份验证用户的方式
-在首次加载时传递他们想要查看的页面和他们的电子邮件地址。
这的基础是简单的对称密钥认证 - 后面的所有内容都是将其混合在一起的方法。
将您的数据组合在一起(电子邮件地址,着陆页),然后使用强密钥进行哈希处理。
在另一端进行解密,完成。
如果您的密码(密钥)很难猜测,此方法是安全的 - 以下是一种难以破解的方法。 身份验证 有几种方法可以做到这一点 - 如果您可以访问他们的服务器(或者那里有人可以为您插入一些代码),则以下内容将起作用。
创建一个执行以下操作的php脚本。 我已经过度设计了这个示例,以演示使哈希字符串更难破解的多种方法 - 您可以选择自己的方式! (伪代码)
$serverTimeStamp = timestamp;

$additionalNoise = "THEcat1sch33sy";

$time = $serverTimeStamp . "XAB"; <- needs to be a random code as delimeter.
$data =  $additionalNoise + "email@email.com";
$salt = "wh4tW0u1dB4tm4nD0?" + $serverTimeStamp;

需要使用可逆哈希算法对$password进行哈希处理(可以从mcrypt开始学习)。

$encrypted = mcrypt of $data and $salt ($salt is shared key);

$authenticationcode = $time . $encrypted;

这将为您提供一个带时间戳的强随机字符串,其前面是XAB,然后是一个随机散列字符串。
然后将其传递给您的用户验证脚本。
<iframe src="http://yoursite/validate/COMPLETELYRANDOMSTRING"></iframe>

接下来您需要反向处理。

重要提示(修正)- 我完全忘记了一个重要的要素 - 将发送给您的随机字符串存储在数据库中。这些字符串是“一次性”的 - 如果您再次收到相同的字符串,则会被视为攻击。

这一切都由时间戳在盐中并位于字符串开头来实现 - 可以在一天内使用完全不同的字符串发送相同的数据1000次。

Get random string.

get time-stamp from front of random string -> using regex / index of looking for numbers and then XAB (hence the random XAB string - it is just a separator)

$timeStamp = "10200192XAB";

"wh4tW0u1dB4tm4nD0?" <-shared secret key.

$salt (secret key) = "wh4tW0u1dB4tm4nD0?" + $timeStamp;

使用盐进行解密

您将获取以以下内容开头的数据

"THEcat1sch33sy" (your additional noise) (which is also a fixed shared key in effect)

只需删除"THEcat1sch33sy",您就可以得到您的电子邮件地址(然后您需要验证一下,以防万一随机字符串实际上在开头输出"THEcat1sch33sy")。

瞧 - 不是100%,但相信我 - 如果我试图进入您的服务器 - 我不会用这种方式尝试!

密码页面结束

Simply add it to the $data - so you would pass $email + "seperator" + $coursepage.

希望这能有所帮助(并且清晰易懂)。

非常感谢Graham - 这正是我在寻找的。您以最好的方式解释了它 - 感谢您花时间编写如此详细的回复。 - Gublooo
很高兴我能帮到你,可惜我没有得到赏金:-( 嘿嘿。相信我,我曾经为了做类似的事情而苦思冥想了好几天,所以很高兴能够帮你避免这种痛苦(希望如此!) - GrahamTheDevRel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接