我希望在用户进入网站之前在HTML中绘制一个等待屏幕,因为一些长时间运行的auth进程是我无法控制的。我希望该屏幕完全符合HTTP标准,即:
200 OK
(这会消除显示带有加载指示符的空页占位符并在后台使用AJAX调用加载内容的选项)我能看到的唯一“第三种方式”是依靠标准的302重定向。但是我需要请求的实际内容,导致302响应在等待第二个请求时呈现给用户(“请等待”信息或其他内容)。在大多数(所有?)情况下,浏览器不会绘制这些请求的内容,只是等待重定向数据。
问题是:
302 Redirect
页面的状态,没有任何内容最初没有违反协议?答案 0 :(得分:5)
对你的问题的简短回答可能是"实际上不可能"。
但你可能很幸运。
规范要求客户端立即转到302响应中指定的新URL。没有办法等待,现在回复的概念将被渲染。
您期望某些进程应等到冗长的身份验证过程结束。
这样的过程必须能够
1)启动身份验证过程
2)渲染一些"等待"页面
3)检查认证过程的结果
4)身份验证成功后,将您重定向到那里
步骤1 - 从服务器端启动身份验证过程可能是真正的问题,因为您无法访问目标站点的Cookie和其他身份验证资源。您正在为另一个域提供服务,因此您将无法阅读此安全相关内容,只有您的浏览器知道这些内容。但我会假设,你会以某种方式管理(要求你的用户提前告诉你这类信息)。
然后您的Web服务器将启动您的客户端的身份验证过程。这很奇怪,但您可以通过从服务器向目标站点发起http请求来尝试这样做。这必须是异步完成的,因为我们还需要做一些其他事情,比如为用户提供一些渲染内容。
第2步 - 渲染一些"等待页面。 要在浏览器端呈现内容,您可以返回包含200状态代码的页面。我不认为,这是打破http。你会回复一些不错的等待片刻"内容加上添加"刷新"标题在短时间内启动页面刷新(如在2秒左右)。
步骤3 - 检查身份验证过程的状态:您的服务器将从上一步的刷新表单获得另一个请求。您的服务器必须知道此活动的上下文,可能是会话ID。在这种情况下,它会发现,有一个身份验证过程正在运行。如果验证尚未完成,请重复步骤2.
步骤4 - (仍然在您的服务器上)如果身份验证已完成,请收集客户端作为经过身份验证的用户连接到目标服务器所需的所需信息,并返回302,其中包含指向目标服务器的链接。这假设,链接允许连接"认证"方式。
这种方法很可能在步骤1和/或4中失败。但可能会出现一些情况(取决于目标服务器)。
等待完整身份验证的进程的另一个选项是在浏览器中。使用AJAX进程不会破坏HTTP,它只是另一个并行运行的进程。
你可以渲染一些"等待"内容,然后尝试通过AJAX连接到目标服务器。
但是,在这里您尝试进行某种跨站点脚本编写,因此除非目标服务器不允许您发出此类请求(搜索CORS,您的Web浏览器正在另一个域的上下文中运行),web浏览器会拒绝这样的请求。
假设您成功,您的AJAX流程将尝试连接,一旦成功,它将管理将页面重定向到目标页面。
您可以修改第一个建议的解决方案 - "服务器端选项",通过接管与目标服务器的所有通信并向您的客户提供类似的内容。
如果您使用生命线"浏览器"," MyServer"," TargetServer"来绘制Sequence diagram会很棒。
最大的问题是,如果您希望对其他域进行身份验证,而不是您所服务的域,则要求您的用户与您分享非常隐私的信息。浏览器会尽力阻止此类行为,您的用户可能愿意与您的应用分享此类信息,但此类行为非常棘手。
对我来说听起来,你正试图以某种方式解决域上的慢速身份验证过程,你无法控制。这往往导致非常绝望的情况"我没有足够的力量去做,但我必须"。拒绝这样一个要求的好理由可能是“#34;它需要打破几个与安全相关的标准。"
答案 1 :(得分:2)
最简单的解决方案是使用 multipart / x-mixed-replace 内容类型响应,第一部分是临时等待页面,次要部分是实际最终内容。 这个内容可以正确地提供200 OK。
初始响应应如下所示,并应尽快刷新给用户 同时保持HTTP连接打开
HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace;boundary=MYBOUNDARYSTRING
--MYBOUNDARYSTRING
Content-Type: text/html
<html><body><!-- your waiting page content here --></body></html>
--MYBOUNDARYSTRING
当您的最后一页准备就绪时,您只需要提供将要显示的第二个HTML部分 而不是第一个
Content-Type: text/html
<html><body><!-- your final page here --></body></html>
--MYBOUNDARYSTRING
--
最后的“ - ”表示浏览器内容已完成且没有其他部分。
大多数现代浏览器会在第一个内容部分可用时正确替换第二个内容部分,但这是特定于用户代理的,并且已知旧版本的Internet Explorer无法正确处理此MIME类型
您可以使用单个HTML文档实现相同的分块响应技术,并依靠Javascript和/或CSS直观地替换用户的内容。
例如:
立即刷新初始响应:
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked
6E
<html><head><!-- load my CSS and JS files --></head><body>
<div id="waiting"><!-- my waiting content --></div>
当您的最终内容准备就绪时,发送一个新的块:
3E
<div id="final"><!-- my final content --></div></body></html>
0
要确保显示#final div而不是#waiting,您可以:
<script>$("#waiting").hide();</script>
代码</body>
之类的内容
或使用CSS定位来确保#final显示在#waiting之上,类似于
<style> body { position: relative; margin: 0; padding: 0 } body > div { position: absolute; top: 0; left: 0; width: 100% } #waiting { z-index: 0 } #final { z-index: 1 } </style>