【问题标题】:Using Datazen in an iframe with external authentication在具有外部身份验证的 iframe 中使用 Datazen
【发布时间】:2016-05-10 04:28:55
【问题描述】:

我能够通过 HTTPWEBREQUEST 从带有 VB.NET 的代码隐藏中成功使用 datazen 的外部身份验证,但我不清楚如何将它与 iframe 甚至 div 一起使用。我在想也许授权 cookie/令牌没有遵循 iframe? datazen 开始正确加载,但随后它重定向回登录页面,就好像它没有经过身份验证一样。不知道如何做那部分,这些东西对我来说很新,任何帮助将不胜感激!

网页错误包括:

-OPTIONS url 发送 @jquery.min.js:19b.extend.ajax @jquery.min.js:19Viewer.Controls.List.ajax @Scripts?page=list:35Viewer.Controls.List.load @Scripts?page=list:35h.callback @Scripts?page=list:35 VM11664 about:srcdoc:1

XMLHttpRequest 无法加载 http://datazenserver.com/viewer/jsondata。预检响应包含无效的 HTTP 状态代码 405Scripts?page=list:35

load():无法加载 JSON 数据。 V…rC…s.List {version: "2.0", description: "KPI & dashboard list loader & controller", url: "/viewer/jsondata", index: "/viewer/", json: null…}(匿名函数)@Scripts?page=list:35c@jquery.min.js:4p.fireWith@jquery.min.js:4k@jquery.min.js:19r@jquery.min.js:19 脚本?page=list:35

GET http://datazenserver.com/viewer/login403(禁止)(匿名函数)@Scripts?page=list:35c@jquery.min.js:4p.fireWith@jquery.min.js:4k@jquery.min.js :19r@jquery.min.js:19

            ' ''//////////////////////////////////
            Dim myHttpWebRequest As HttpWebRequest = CType(WebRequest.Create("http://datazenserver.com/"), HttpWebRequest)
            myHttpWebRequest.CookieContainer = New System.Net.CookieContainer()

            Dim authInfo As String = Session("Email")


            myHttpWebRequest.AllowAutoRedirect = False

            myHttpWebRequest.Headers.Add("headerkey", authInfo)
            myHttpWebRequest.Headers.Add("Access-Control-Allow-Origin", "*")
            myHttpWebRequest.Headers.Add("Access-Control-Allow-Headers", "Accept, Content-Type, Origin")
            myHttpWebRequest.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")

            Dim myHttpWebResponse As HttpWebResponse = CType(myHttpWebRequest.GetResponse(), HttpWebResponse)
            Response.AppendHeader("Access-Control-Allow-Origin", "*")

            ' Create a new 'HttpWebRequest' Object to the mentioned URL.

            ' Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
 
            Dim streamResponse As Stream = myHttpWebResponse.GetResponseStream()
            Dim streamRead As New StreamReader(streamResponse)


            frame1.Page.Response.AppendHeader("Access-Control-Allow-Origin", "*")
            frame1.Page.Response.AppendHeader("headerkey", authInfo)
            frame1.Attributes("srcdoc") = "<head><base href='http://datazenserver.com/viewer/' target='_blank'/></head>" & streamRead.ReadToEnd()

【问题讨论】:

    标签: asp.net vb.net-2010 datazen-server


    【解决方案1】:

    您可能需要在客户端做更多的工作,但出于安全考虑,我不知道您是否可以这样做。

    Datazen 中的外部身份验证如下所示:

    User-Agent         |  Proxy               |  Server
    -------------------|----------------------|------------------------------------
    1. /viewer/home   --> 2.  Append header  --> 3.  Check cookie (not present)
                      <-- 5.  Forward        <-- 4.  Redirect to /viewer/login
    
    6. /viewer/login  --> 7.  Append header  --> 8.  Append cookie
                      <-- 10. Forward        <-- 9.  Redirect to /viewer/home
    
    11. /viewer/home  --> 12. Append header  --> 13. Check cookie (valid)
                      <-- 15. Forward        <-- 14. Give content
    
    16. .................. Whatever the user wanted ..........................
    

    因此,即使您正在使用带有标头的代理,您仍然会得到它使用的 cookie。

    现在,这只是上下文。

    根据您对症状的描述,我的猜测是 myHttpWebResponse 应该有一个 cookie 集(我相信是 DATAZEN_AUTH_TOKEN),但它基本上被扔掉了——你没有在任何地方使用它。

    您需要告诉您的浏览器客户端将该 cookie 附加到对 Datazen 服务器域的任何后续(基于 iframe)请求中,但由于安全限制,我认为这是不可能的。不过,我对 CORS 了解不多,所以可能有办法允许它。

    我不知道是否有任何好方法可以做你想做的事情。充其量,我可能会想到一个可行的 hack 的开始,但我什至找不到一个好的方法来实现它,而且你真的不想去那里。

    基本上,如果您希望在 iframe 中嵌入 Datazen,我会回避外部身份验证。无论如何我都会回避它,但尤其是在那里。

    但是,如果您绝对确定需要它而不是 ADFS 之类的东西,则需要某种方法将该 cookie 放入您的 iframe 请求中。


    我认为完成这项工作的唯一方法是将所有内容放在同一个域中:

    • www.example.com
    • datazen.example.com(可能是你的代理)

    然后,您可以从您的响应中设置一个 cookie,该 cookie 存储了Session("Email") 的一些加密(并且可能过期)形式,并将其传递回您的 html 中。

    这使您的 iframe 相对简单,因为您只需告诉它将查看器加载到主页即可。大意是:

    <iframe src="//datazen.example.com/viewer/home"></iframe>
    

    在您的代理中,您将检测您的网络服务器设置的 cookie,解密电子邮件令牌,确保它没有过期,然后在对 Datazen 服务器的后续请求中设置一个标头。

    这可以在几个地方进行简化,但这应该尽可能地适用于您的原始实现,只要您可以弄乱 DNS 设置。


    我想另一个版本可能涉及将参数传递给您的代理,并共享一些通用加密密钥。这将使您不必在同一个域上。

    所以如果你有类似的东西:

    var emailEncrypted = encrypt(Session("Email") + ":somesalt:" + DateTime.UtcNow.ToString("O"));
    

    然后使用您想要设置 iframe 的任何模板语言:

    <iframe src="//{{ customDomain }}/viewer/home?emailkey={{ emailEncrypted }}"></iframe>
    

    然后您的代理检测到 emailkey 参数,对其进行解密,并检查是否过期,这可以工作。

    现在您可以选择如何处理这个问题,因为 Datazen 会给您一个 302 到 /viewer/login 来获取一个 cookie,并且您需要确保通过它传递正确的 emailkey .

    1. 我会做什么,您可以在代理中接受 emailkey 参数,自己设置一个全新的 cookie,然后在后续请求中注意该 cookie。

      尽管此时,将您的外部身份验证模式切换为仅使用 cookie 可能是合理的。无论如何,这可能是一个更好的版本,假设这是您使用 Datazen 的唯一地方,并且您可以安全地更改如此基本的东西。这将大大减少您的业务逻辑。

      但是,您不必这样做。如果你不想改变它,你可以只检查 cookie,然后把它变成一个标题。

    2. 您应该做 (1),但只是为了更好地衡量,我不确定的一件事是您是否可以将用户直接传递给 /viewer/login 以从 Datazen 获取 cookie。通常你不会,但看起来你应该可以。

      假设它按预期工作,您可以换掉那个 URL。据我所知(尽管我必须仔细检查),标题实际上只需要一次,以设置 cookie。所以如果你这样做了,你应该得到 cookie,然后不再需要 URL 参数,所以强制导航就不用担心了。

    当然,您需要确保那里有良好的加密形式,并且过期模式很重要。但如果你做得对,你应该能够确保这一点。

    【讨论】:

    • 是的,我能够获取 DATAZEN_AUTH_TOKEN cookie 并将其添加到我的请求/响应中(在我发表这篇文章之后),我想我在某个地方也做错了,但你是对的,它似乎也会在某个时候迷路。我可以看到 Web 响应中的所有内容,就好像我已通过身份验证一样,但我不知道如何正确处理它。用这个网络请求的东西原谅我的新手能力。我也尝试过用 ajax 做这个客户端,但我从来没有能够通过这种方式正确地获得身份验证。
    • @Luke 我真的不记得HttpWebRequest 中 cookie 的默认行为,但我可以想象它是否通过重定向支持它们,在这种情况下这是有道理的。您的响应将具有完全经过身份验证的正文,但随后您将其放入 iframe 中,并且您的 cookie 当然不会与它一起传递。我真的不确定是否有任何可靠的方法可以做到这一点。除非,我想,如果你可以把所有东西都放在同一个域(带有子域),你可以设置一个 cookie 并在你的代理上使用它,或者直接用于外部身份验证。那会奏效的。
    • @Luke 我稍微编辑了我的答案,以添加一个关于它如何工作的理论。同样,我对 CORS 知之甚少,但这应该避免大多数头痛。至少这是一件事情。对于它的价值,我可以肯定地告诉你,从长远来看,这将变得太麻烦,除非你绝对需要它,否则你可能不应该继续走这条路。不推荐使用外部身份验证,并且几乎不按原样支持它。我了解您的用例,我相信这应该可行,但这是我的警告。
    • 有没有办法通过标准的 datazen 身份验证凭据?如果除了从后面读取之外您无法对其进行任何操作,我不确定进行外部身份验证有什么意义。即使我必须打开另一个页面或加载一个 div,那也没关系。我只是想阻止我们的网站进行多次登录。我们当前对我们网站的身份验证是使用独立的 sql 服务器。 Windows 身份验证是不可能的,因为我们有外部客户。
    • @Luke 我已经编辑了我的答案以包含一个可能更适合您的工作流程。需要付出更多的努力才能做到正确,但应该不会太特别。
    【解决方案2】:

    我最终只是抓住了用户名和密码字段并使用 javascript 输入它们。但是这个piece 帮助了我很多。你必须确保你设置了

    document.domain ='basedomain.com';

    在两个站点上的 javascript 中访问 iframe 内容,否则您将遇到跨域问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      • 2016-03-25
      • 2019-04-12
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      • 2010-12-25
      相关资源
      最近更新 更多