【问题标题】:WIF cannot redirect to a URL containing a hash after federated authentication联合身份验证后,WIF 无法重定向到包含哈希的 URL
【发布时间】:2013-06-29 17:14:18
【问题描述】:

我正在使用 WIF 和使用 ThinkTecture STS 的联合安全模型。

当我尝试请求 url:http://domain.com/#page 时,WIF 未在身份验证后重定向到正确的页面。

wctx 中的 ru 参数不包含 /#path 的正确路径。相反,它会忽略散列及其后面的所有内容,因此 ru 参数只是 /。没有哈希的普通网址可以正常工作。

是否有针对此的锻炼或我的网址格式不正确?
有什么建议吗?

【问题讨论】:

    标签: wif single-page-application federated-identity thinktecture-ident-server thinktecture-ident-model


    【解决方案1】:

    看起来它的浏览器没有将 url 的哈希部分发送回服务器。我相信这是一个 HTTP 标准,因为哈希部分最初仅用于客户端锚标记。

    有使用 ajax/javascript 的变通方法,但由于我使用的是简单的 GET 请求,这似乎是不可能的。

    查看这些类似的问题,这些问题可以解释问题...

    How to get Url Hash (#) from server side

    do browsers remove # in URL automatically?

    【讨论】:

      【解决方案2】:

      这就是哈希片段的全部意义——它们最终不会出现在服务器上。

      【讨论】:

        【解决方案3】:

        您可以通过发出 JavaScript 来执行重定向来保留哈希部分,而不是立即重定向。 JavaScript 代码可以通过 window.location.hash 访问 hash 部分,并使用它来构建 ru。

        您需要将页面配置为允许未经身份验证的用户(这样 WIF 被动身份验证就不会启动)。然后你可以在页面代码中处理未经身份验证的用户。

        您可以在应用程序启动代码(例如 Web 窗体中的 Global.asax.cs)中挂钩 FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider 事件。

        例如(Web 表单):

        public class Global : HttpApplication
        {
            protected void Application_Start(object sender, EventArgs e)
            {
                FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider 
                += this.RedirectToIdentityProviderViaJavaScript;
            }
        
            const string RedirectHtml =
            @"<html>
                <head>
                    <script type='text/javascript'>
                        function authenticate(url, utcTimeString) {{
                            var ru = window.location.pathname + (window.location.hash || '');
                            var wctx = 'rm=0&id=passive&ru=' + encodeURIComponent(ru) + '&wtc=' + encodeURIComponent(utcTimeString);
                            url += '&wctx=' + encodeURIComponent(wctx);
                            window.location = url;
                        }}
                    </script>
                </head>
                <body onload=""authenticate('{0}', '{1}');"">
                </body>
            </html>";
        
            private void RedirectToIdentityProviderViaJavaScript(object sender, RedirectingToIdentityProviderEventArgs e)
            {
                var fam = FederatedAuthentication.WSFederationAuthenticationModule;
                var msg = new SignInRequestMessage(new Uri(fam.Issuer), fam.Realm);
                var stsUrl = msg.WriteQueryString();
                var utcTime = WebPageRoutines.EncodeUtcTimeString(DateTime.Now);
                var html = string.Format(RedirectHtml, WebPageRoutines.JavascriptEncode(stsUrl), WebPageRoutines.JavascriptEncode(utcTime));
                Response.ClearContent();
                Response.Write(html);
                Response.Status = "200 OK";
                Response.End();
            }
        }
        

        被警告不能混音?使用这种方法的 # 部分参数。 ru 在 STS 重定向 (Thinktecture IdentityServer v2) 中幸存下来,但 WIF 似乎在 STS POST 后的最终重定向上搞砸了。

        它将放置 ? # 部分之后的部分。
        http://www.somewebsite.com/page?param=1&other=2#hashbit
        变为:
        http://www.somewebsite.com/page#hashbit?param=1&other=2

        【讨论】:

          【解决方案4】:

          最好使用 CreateSignInRequest 从 web.config 中获取所有参数。猜猜它解决了查询字符串的问题。使用 MVC 的示例

                  const string redirectHtml =
                      @"<!DOCTYPE html>
                        <html>
                          <head>
                              <meta charset='utf-8'>
                              <script type='text/javascript'>
                                  function authenticate(url) {{
                                      var ru = window.location.pathname + (window.location.hash || '');
                                      window.location = url.replace('REPLACEWITHURL', encodeURIComponent(ru));
                                  }}
                              </script>
                          </head>
                          <body onload=""authenticate('{0}');"">
                          </body>
                      </html>";
          
                  var authenticationModule = FederatedAuthentication.WSFederationAuthenticationModule;
                  var message = authenticationModule.CreateSignInRequest("passive", "REPLACEWITHURL", false);
                  var stsUrl = message.WriteQueryString();
                  var html = string.Format(redirectHtml, HttpUtility.JavaScriptStringEncode(stsUrl));
                  filterContext.Result = new ContentResult { Content = html };
          

          【讨论】:

          • 这很好用。我不在 MVC 应用程序中,所以我的解决方案已经过调整。 filterContext.Result = new ContentResult { Content = html }; 恢复为原来的解决方案:Response.ClearContent(); Response.Write(html); Response.Status = "200 OK"; Response.End();
          • 需要注意的是,在这个解决方案中,“REPLACEWITHURL”并不是指示开发者在其中放置一个 URL。这是编写重定向页面时事件要替换的字符串。
          猜你喜欢
          • 2013-06-28
          • 2012-01-15
          • 1970-01-01
          • 2011-06-23
          • 1970-01-01
          • 2019-09-10
          • 1970-01-01
          • 2017-04-06
          • 1970-01-01
          相关资源
          最近更新 更多