我可以从其他网站呈现表单吗
Posted
技术标签:
【中文标题】我可以从其他网站呈现表单吗【英文标题】:Can I render a form from another website 【发布时间】:2011-04-26 06:22:18 【问题描述】:我在网站 A 上有一个用户,我需要将他登录到网站 B(不在我的控制之下),但不会危及他在网站 B 上的密码。网站 B 没有 API,这使得这比网站更复杂应该。
我的第一个选择是在网站 A 上呈现我自己的表单,用户在我的表单中输入他的网站 B 密码,我以某种方式安全地将他的网站 B 密码传递给网站 B 以让他登录。这意味着我必须先通过将密码从客户端安全地传递到我的服务器,然后将其再次从我的服务器安全地传递到最终网站。这就是我猜我必须做的,但我没有计划如何安全地实现这 2 个跃点,所以我担心我可能会以某种方式暴露用户的密码。
所以我想到了第二种选择,即将网站 B 中的同一个网站 B 渲染到我的网站上。但是B网站的表单是大页面的一部分,这样可以吗?
如何将表单本身的代码与整个页面的代码隔离开来 如何在我的网站上显示表单。我希望用户看到它。想到了 iframe,但从未使用过它 当用户单击提交按钮或在我的网站上呈现表单以某种方式使其无效时,表单是否仍然有效这是我想到的两种不同的解决方案。我欢迎为每个人提供答案,也欢迎提出可能更容易的替代第三种方法的答案。
【问题讨论】:
为什么不使用OpenID等第三方认证机制? @Mitch 我希望,但我对网站 B 没有任何控制权。他们没有 API,也不提供 OpenID。 对您要登录的页面一无所知。但是今天很多网站都使用了针对这些类型操作的保护措施。因为在某种程度上你想要完成的基本上是一个跨站点请求伪造(en.wikipedia.org/wiki/Csrf) 在这个问题上看不到任何意义。without jeopardizing his password on website B
是什么意思,如果密码仍然发送给 B? 事实上,用户在您的站点上而不是在站点 B 上危及他们的密码。 这看起来像是一种收集站点 B 用户密码的网络钓鱼攻击。你很难证明你没有恶意。为什么要干预站点 B 和它的用户呢?
@ Col. Shrapnel 危及他们的密码意味着密码在传输时没有完全通过隧道传输。我不必向你解释我在做什么。如果您不明白为什么一个站点可能需要代表用户与另一个站点交互并且您想假设它一定是恶意的,那么您应该熟悉 Web 2.0 和 OpenID、OAuth 和 API 等概念。今天的网站应该是非常互动的,而不是孤立存在的。
【参考方案1】:
只要您在自己的网站上使用 SSL,就不会存在泄露用户密码的重大风险(除非您进行某种金融交易,请澄清)。
我的建议是,不要复制他们的表格。相反,请复制该表单生成的 HTTP POST。您可以完全以编程方式执行此操作,并且用户永远不会离开您的站点,但(在大多数情况下)结果将是用户也登录到他们的站点。
如果要处理某种散列字段,请(以编程方式)请求其表单页面并使用您收到的任何值将 返回 发送到第二个站点,以便验证请求。他们的服务器不知道请求不是来自浏览器(实际上,如果您愿意,您可以将用户代理添加到 HTTP 标头)。
我已针对 Verizon 的网站和 LinkedIn(均出于合法目的)使用了这种方法,并且它有效。
回顾一下:
了解他们的 HTTP POST 的结构。
向您的站点添加登录表单。
在代码中处理请求,使其看起来像 POST 他们的 网站预期。
从您的代码发布到他们的网站。
在您的站点上显示对用户的响应(如果需要), 重定向,随便。
【讨论】:
【参考方案2】:您所描述的场景可能很棘手甚至不可能。您面临的主要问题是您如何将登录凭据发布到站点 B,以使成功登录本身返回的 cookie 最终出现在用户的浏览器中并属于站点 B,以便站点 B 在用户实际上导航到那里。
有几个人建议将表单发布到服务器上的 php 文件中,然后让它从服务器登录到服务器。这个解决方案几乎永远不会奏效。即使站点 B 接受您的服务器-服务器登录(它可能会接受,因为您可以伪造任何您想要的浏览器),它将是 您的 网络服务器,它将获取新的 cookie,并且 与会话相关联的 网络服务器的 IP。即使您将 cookie 返回到浏览器,它也会将其保存到 您的 站点(站点 A),并且不会在浏览器到达站点 B 时将其提交到站点 B,因此用户将保持退出状态B站的。
因此,您在这里唯一能做的就是在您的服务器上为他们的网站托管一个登录表单。这意味着您必须向浏览器发送一个表单,该浏览器的 ACTION 指向站点 B 的登录表单。这也意味着每当用户单击登录按钮时,控制权就会转移到站点 B:用户将离开您的站点,而您将失去他。
第二种方法有两个主要的技术问题:一个是站点 B 可能有 XSS 预防,实际上可能会阻止您将内容发布到他们的登录页面。另一个问题是,如果您的网站使用 SSL,浏览器将花费大量时间让您向其他网站提交表单。这些都不是你可以自己解决的。
唯一干净的解决方案是真正与站点 B 坐下来,制定一些关于通用身份验证的计划,或者至少是一个身份验证 API。您可以尝试表单交叉发布解决方案,但很有可能您会遇到不喜欢的问题。
【讨论】:
【参考方案3】:请参阅:Sockets
-
研究 SiteB 的登录表单 html 以收集字段名称、预期值和操作 URL 的列表。
在您自己的网站上重新制作表单,使用相同的字段名称。操作 url 应指向您自己服务器上的处理脚本。此时需要注意的是,如果站点 B 在其登录表单页面加载时使用了一些特殊的令牌字段或 cookie 集。如果是这种情况,请使用套接字连接并获取站点 B 登录页面的新副本。您需要知道HTTP message standards and proper request body structure 才能完成此任务。然后,将检索到的文本解析为要在您自己的页面上使用的令牌字段或 cookie 名称和值。
用户在您的表单中输入站点 B 的用户名和密码。提交时,表单结果将传递给您的处理程序脚本。
您的处理程序脚本使用套接字作为常规 POST 请求连接到站点 B 的操作 url 目标。此 POST 请求包括站点 B 在前面几个步骤中提供的任何 cookie 和令牌名称/值。您需要再次遵循 HTTP 协议消息结构指南才能完成此操作。
站点 B 使用您的用户信息进行身份验证。您的处理程序脚本正在等待响应。
站点 B 响应处理程序脚本。您需要研究站点 B 返回的典型响应,以了解如何解析任何响应文本(并再次学习如何解析 HTTP 消息),包括返回的 cookie 标头。
您的处理程序脚本需要在某处保存与用户匹配的日志,该日志与站点 B 成功验证后返回的任何 cookie 值相匹配。在未来对站点 B 的任何请求中,再次使用套接字以伪装为用户,并传递 cookie 标头/val用于标识他们(即:您的)到站点 B 的登录会话。
请记住,您可能希望就您在站点 B 上所做的事情保持公开和诚实的对话,或者您可以是 liable for civil action。
【讨论】:
【参考方案4】:我会尝试概述一个解决方案,但它可能不正确,甚至可能不是您想要的,而且绝对不切实际。
根据我对 XSRF 的了解,如果目标站点完成了作业,您将无法模仿从您的域提交的表单。
除了目标站点之外,唯一可以访问用户凭据的是浏览器。所以你真正需要做的是成为一个浏览器。这意味着您必须说服用户他可以将他的登录信息交给其他站点。我不知道你怎么能做到这一点,我不会相信这样的事情。 (另一种选择是欺骗他(网络钓鱼),但这是非法的,我认为您甚至不会考虑。)
在您设法说服用户向您提供他的数据后,您仍然必须像浏览器一样行事。您必须实现一个系统来为每个用户存储 cookie,以便在您登录时创建会话。
这样做后,您将使用用户的数据登录,但用户不会。因此,您还需要通过您的网站实现用户需要的任何其他操作。
我的建议:
要么联系目标站点并设置一个协议,您可以使用该协议对来自您站点的用户进行身份验证。有一些非常酷的 iframe 技术可以做到这一点。阅读这篇文章以获取出色的演示文稿http://softwareas.com/cross-domain-communication-with-iframes。
或者让用户打开一个带有该站点登录页面的弹出窗口。确保弹出窗口中的地址栏可见。
【讨论】:
+1 好建议。您建议我尝试使用该网站设置什么协议? 查看我添加到帖子中的文章。【参考方案5】:这完全取决于您要发布到的服务器如何处理 CSRF [跨站点请求伪造],因为这基本上就是您正在做的事情。例如,如果他们使用的是相对较新的 Django,那么来自外部服务器的 POST 请求默认会失败,除非它们包含 csrf cookie 值。
如果您也可以控制要发布到的服务器,则可以解决此问题。
【讨论】:
csrf 令牌是我上面概述的两个选项的问题,还是只是其中一个问题? 两者都可能。 Django 的工作方式是每个 POST 请求都需要一个 csrf_token 字段,该字段与浏览器已建立的会话中的字段相匹配。本质上,您在这两种情况下所做的事情是相同的:您正在创建自己的表单来反映所需的数据。这正是 CSRF 保护应该防止的。 话虽如此,根据网站的年龄(以及建造它的人),很可能没有 CSRF 保护。【参考方案6】:我并没有真正得到您想要做的事情,如果只是登录该站点,您可能可以执行以下操作:Mainsite:
<iframe id="logon" src="/logonto-other.html"></iframe>
/logonto-other.html:
<form onsubmit="top.logon.style.visibility='none';" action="http://other-site.com/login" method="post">
<dl>
<dt><label for="user">Name</label></dt>
<dd><input name="user" />
<dt><label for="pass">Password</label></dt>
<dd><input name="pass" />
</dl>
<?php //code that acquires hash from other site
// Don't know site B so can't write this one yet.
?>
<input type="submit" value="Login" />
</form>
这样用户只会登录到另一个站点,您与它的交互能力仍然会受到限制(或者我认为我应该从未学习过同源策略,因为我从未觉得有任何限制我所做的。也许今天的浏览器更严格)。
关于“2 hop”的事情,您的服务器 A 上是否有证书和 SSL/HTTPS 支持?服务器B有这个吗?你认为你能让用户相信你拥有他们的密码吗?一个提示是您添加一段解释情况和一个链接,用户可以在其中联系站点 B 以向他们施加压力以实施 OAuth 和/或 OpenID?
即使您的服务器上没有 HTTPS,您也可以使用 javascript 或 Java 小程序来加密密码(网络上的 JavaScript 中必须有 PGP。虽然,如果浏览器地址栏变成绿色,用户可以更容易地决定是否信任你。
想要我的问题的一些答案,我们可以知道站点 B 是什么吗?而你到底想做什么,也许我们可以一起解决。
祝你好运。
【讨论】:
【参考方案7】:要将表单与较大的页面隔离开来,请找到<form>
和</form>
标记,并且只复制它们之间的任何和元素。现在将该表单放在您的页面上,其操作仍指向它在原始网站上指向的 URL。密码永远不会通过您的服务器。
【讨论】:
以上是关于我可以从其他网站呈现表单吗的主要内容,如果未能解决你的问题,请参考以下文章