11

我々はインターネット上でそれを使用することができますので、私は、フォーム認証にSQL-Serverレポートサービス2012(SSRS 2012)を切り替えています。SSRS:なぜ "HTTP 400 Bad Request - Request too Long"が発生するまでSKAクッキーが生成されるのですか?

どこでもSSRS 2012のフォーム認証のサンプルが見つかりませんでしたので、SSRS 2008R2を1つ取り、Single Sign-On(SSO)用に2012に適応させなければなりませんでした。

すべてが期待どおりに働いているように見えたその時点で。私はSSOをドメイン間で動作させることさえできました。

しかし、今、私は問題を抱えている:

私は右のそれHTMLディスプレイ用のtdのボーダーサイズを変える少しJavaScriptを挿入しなければならなかったので、私は、GoogleのChromeですべてのレポート(200以上)をテストしていました非IE5-QuirksMode。およそ第50回報告した後、私は突然だ:

- 、その後

「HTTP 400不正な要求が長すぎ要求」私は以前に仕事をしなかったものも含め、他のレポートを表示できませんでした。

問題は、あまりにも多くのクッキーに起因すると思われる、と私はいくつかの「* _SKA」を削除したとき確かに、(セッションキープアライブ?)クッキー、それが再び働き始めました。

SSRS Sucks

私の問題は、今私は、この「クッキーオーバーフロー」が発生かわからないということです。 これはChromeのバグ、バニラSSRSのバグ、新しいフォーム認証によるバグについてもわかりません。

私はクッキーとは何かを持っている新しいフォーム認証で行うすべてはこれです:

using System; 
using System.Collections.Generic; 
using System.Text; 


namespace FormsAuthentication_RS2012 
{ 


    internal class FormsAuthenticationWorkaround 
    { 

     public static void RedirectFromLoginPage(string strUser, bool createPersistentCookie) 
     { 
      //string url = System.Web.Security.FormsAuthentication.GetRedirectUrl(strUser, true); 
      string url = GetRedirectUrlWithoutFailingOnColon(strUser, createPersistentCookie); 
      SQL.Log("User: '" + strUser + "' ReturnUrl", url); 

      if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Response != null) 
       System.Web.HttpContext.Current.Response.Redirect(url); 
     } 


     // https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web.Security/FormsAuthentication.cs 
     // @MSFT: WTF are u guys smoking ? 
     public static string GetRedirectUrlWithoutFailingOnColon(string userName, bool createPersistentCookie) 
     { 
      if (userName == null) 
       return null; 

      System.Web.Security.FormsAuthentication.SetAuthCookie(userName, true, "/"); 

      string returnUrl = null; 

      if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Request != null) 
       returnUrl = System.Web.HttpContext.Current.Request.QueryString["ReturnUrl"]; 

      if (returnUrl != null) 
       return returnUrl; 

      returnUrl = System.Web.Security.FormsAuthentication.DefaultUrl; 
      return returnUrl; 
     } 


    } 


} 

そして、このコードは、1が一番下に見ている「sqlAuthCookie」を作成しますように。 "sqlAuthCookie"が1つしかないので、これはフォーム認証バグかもしれません。

問題は、私の知る限りでは、バニラSSRSをどうするフォーム認証とすべてのものとは何の関係もないことを、SKAクッキーのように見えます。私はこの理由として見ることができた

唯一の他の事は、私は、web.configファイルでフォーム認証部に入力された720分にフォーム認証Cookieのタイムアウトの変化です。

<authentication mode="Forms"> 
    <forms loginUrl="logon.aspx" name="sqlAuthCookie" timeout="720" path="/"> 
    </forms> 
    </authentication> 

誰もが私がキープアライブクッキーを(手動でこれらのクッキーを削除する以外)のセッションで洪水に溺れ防ぐために何ができるか知っていますか?

それは離れて、それは非常に迷惑なこと、ユーザーがおそらく非常に理解されませんので、問題になるだろうから、それ自体が私にとっては問題ありません...

答えて

8

固定として記載されている問題SQL Server 2012 SP1のCU7。connect issueでマイクロソフトからのコメントを参照してください)
しかし、まだSQL-Serverの2014に存在します。


は、SQL Server 2012 SP1のCU7インストールできない場合は、後のセクションは、適用されます。

OKを、答えを自分自身を得ました。

キープアライブクッキーは、レポートを開くたびに発行されます。
これは、ブラウザーを閉じずに、110〜120件を超えるレポートを開く(または別のページに更新する)ときに問題になります。

私たちは余分なクッキーを削除し、appxで安全な境界線を設定することで保護します。 120クッキーの想定最大値の1/2

クッキーはHttpOnlyであり、ブラウザを閉じると(セッションクッキー)期限が切れます。
これらは安全でないHttpOnly Cookieです。そのため、JavaScriptを使用して削除しようとしましたが失敗しました。
サーバー側で削除する必要があります。 ReportServerを変更できないため、インラインスクリプトを使用する必要があります。

<body style="margin: 0px; overflow: auto"> 


<script type="text/C#" runat="server"> 
protected string ClearSessionKeepAliveCookiesToPreventHttp400HeaderTooLong() 
{ 
    if(Request == null || Request.Cookies == null) 
     return ""; 

    if(Request.Cookies.Count < 60) 
     return ""; 

    // System.Web.HttpContext.Current.Response.Write("<h1>"+Request.Cookies.Count.ToString()+"</h1>"); 
    for(int i = 0; i < Request.Cookies.Count; ++i) 
    { 
     if(StringComparer.OrdinalIgnoreCase.Equals(Request.Cookies[i].Name, System.Web.Security.FormsAuthentication.FormsCookieName)) 
      continue; 

     if(!Request.Cookies[i].Name.EndsWith("_SKA", System.StringComparison.OrdinalIgnoreCase)) 
      continue; 

     if(i > 60) 
      break; 

     //System.Web.HttpContext.Current.Response.Write("<h1>"+Request.Cookies[i].Name+"</h1>"); 

     System.Web.HttpCookie c = new System.Web.HttpCookie(Request.Cookies[i].Name); 
     //c.Expires = System.DateTime.Now.AddDays(-1); 
     c.Expires = new System.DateTime(1970, 1 ,1); 
     c.Path = Request.ApplicationPath + "/Pages"; 
     c.Secure = false; 
     c.HttpOnly = true; 

     // http://stackoverflow.com/questions/5517273/httpcookiecollection-add-vs-httpcookiecollection-set-does-the-request-cookies 
     //Response.Cookies[Request.Cookies[i].Name] = c; 
     //Response.Cookies.Add(c); 
     Response.Cookies.Set(c); 
    } 

    return ""; 
} 


</script> 

<%=ClearSessionKeepAliveCookiesToPreventHttp400HeaderTooLong()%> 

    <form style="width:100%;height:100%" runat="server" ID="ReportViewerForm"> 
+0

クロムを使用してブラウザを閉じると機能しませんでした。私は手動でクッキーを削除しなければならなかった。私はあなたのサーバー側のソリューションをすぐに試してみます。ありがとう! – kravits88

+0

これは私が変更するまで私には役に立たなかった 'c.Path = Request.ApplicationPath +"/Pages ";'to 'c.Path = Request.Cookies [i] .Path;' – masty

+0

@masty:面白い、Request.Cookies [i] .Pathは私のために働かない。どちらもありませんc.Path = Request.Cookies [i] .Path + "/ Pages"; ServicePack 1 +の最新の累積アップデートをインストールしましたか? –

6

あなたは私が原因で私たちのサイトのアーキテクチャの難しさ、この問題に対するさまざまなソリューションを実装するの多くを持っていたhttp://msdn.microsoft.com/en-us/library/microsoft.reporting.webforms.reportviewer.keepsessionalive(v=vs.100).aspx

+0

ニースが見つかりました。私はそれを試みます。 –

+0

FYI、 "標準" ReportViewerを使用している場合、この設定はReporting Services \ ReportServer \ Pages \ ReportViewer.aspxでRS:ReportViewerHostタグに 'KeepSessionAlive =" false "を追加することで変更できます。 –

+0

@graham mendick:一方で、そうすると、5〜10分間使用しないとエクスポートをクリックするとセッションの期限切れのエラーメッセージが表示されます。 –

3

のReportViewerコントロール にfalseにKeepSessionAliveを設定することができます - どんな理由であれ、私の同僚は、もともと持っていましたReportViewerコントロールではなく、レポートへのリンク付きのiframeを使用することに決めました。単純なクッキーの問題により、開発プロセスの後半でこれを変更しようとするのは嫌です。 - 私のページのサーバーコードが埋め込まれたiframeのドキュメント に設定されたクッキーにアクセスすることができませんでした

  1. 実装Stefanのコードビハインドを修正:私は仕事がなかった試みた

    ソリューション

  2. javacriptの親文書からCookieを変更する - わかりやすいセキュリティ上の理由から、クライアント側のコードからiframe内のCookieにアクセスできませんでした
  3. セッションを存続しないことを伝えるために、レポートURLにパラメータを渡すしようとしました - 「& RS:KeepSessionAlive = False」に追加しようとしましたと*おもちゃ*、エラーが発生することはありませんでしたが、
  4. を動作しませんでしたjavascript into the reports themselvesを注入するアイデア - これは、いくつかの50余りのレポートを変更し、エクスポート/保存されたレポートが備わっています台無しに伴うだろう考えると、これは、

最後にオプションではありませんでしたサーバーチャンスをうかがった後、私は気づきましたレポートサーバー "ページ"フォルダ(C:\ Program Files \ Microsoft SQL Server \ MSRS1 1.SQLEXPRESS \ Reporting Services \ ReportServer \ Pages)には、"ReportViewer.aspx"文書が含まれていました。

あなたは何を知っていますか? これは単純なASP.NETページで、ヘッダーには独自のjavascriptを追加できます!

だから、ここに私のために仕事をやったことです:

私はただのReportViewerページ上のすべてのCookieを削除するには、以下のclient-side cookie-setting code I had found elsewhereを追加し、すべてが突然働いていました!一度に1つのキープアライブクッキーのみ!

<%@ Register TagPrefix="RS" Namespace="Microsoft.ReportingServices.WebServer" Assembly="ReportingServicesWebServer" %> 
 
<%@ Page Language="C#" AutoEventWireup="true" Inherits="Microsoft.ReportingServices.WebServer.ReportViewerPage" %> 
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
 
<html> 
 
<head id="headID" runat="server"> 
 
    <title><%= GetPageTitle() %></title> 
 
</head> 
 
<body style="margin: 0px; overflow: auto"> 
 
    <form style="width:100%;height:100%" runat="server" ID="ReportViewerForm"> 
 
    <asp:ScriptManager ID="AjaxScriptManager" AsyncPostBackTimeout="0" runat="server" /> 
 
    <RS:ReportViewerHost ID="ReportViewerControl" runat="server" /> 
 
    </form> 
 
    <script language="javascript" type="text/javascript"> 
 
     // Beginning of inserted cookies management code 
 
function createCookie(name, value, days) { 
 
    if (days) { 
 
     var date = new Date(); 
 
     date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 
 
\t var expires = "; expires=" + date.toUTCString(); 
 
    } 
 
    else var expires = ""; 
 

 
    document.cookie = name + "=" + value + expires; 
 
} 
 

 
function readCookie(name) { 
 
    var nameEQ = name + "="; 
 
    var ca = document.cookie.split(';'); 
 
    for (var i = 0; i < ca.length; i++) { 
 
     var c = ca[i]; 
 
     while (c.charAt(0) == ' ') c = c.substring(1, c.length); 
 
     if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); 
 
    } 
 
    return null; 
 
} 
 

 
function eraseCookie(name) { 
 
    createCookie(name, "", -1); 
 
} 
 

 
var getCookies = function() { 
 
    var pairs = document.cookie.split(";"); 
 
    var cookies = {}; 
 
    for (var i = 0; i < pairs.length; i++) { 
 
     var pair = pairs[i].split("="); 
 
     cookies[pair[0]] = unescape(pair[1]); 
 
    } 
 
    return cookies; 
 
} 
 

 
var pairs = document.cookie.split(";"); 
 
var cookies = {}; 
 
for (var i = 0; i < pairs.length; i++) { 
 
    var pair = pairs[i].split("="); 
 
    cookies[pair[0]] = unescape(pair[1]); 
 
} 
 
var keys = []; 
 
for (var key in cookies) { 
 
    if (cookies.hasOwnProperty(key)) { 
 
     keys.push(key); 
 
    } 
 
} 
 
for (index = 0; index < keys.length; ++index) { 
 
    eraseCookie(keys[index]); 
 
} 
 

 
     // End of inserted cookies management logic 
 

 
     //Beginning of pre-existing code 
 
Sys.WebForms.PageRequestManager.prototype._destroyTree = function(element) { 
 
    var allnodes = element.getElementsByTagName('*'), 
 
     length = allnodes.length; 
 
    var nodes = new Array(length); 
 
    for (var k = 0; k < length; k++) { 
 
     nodes[k] = allnodes[k]; 
 
    } 
 
    for (var j = 0, l = nodes.length; j < l; j++) { 
 
     var node = nodes[j]; 
 
     if (node.nodeType === 1) { 
 
      if (node.dispose && typeof (node.dispose) === "function") { 
 
       node.dispose(); 
 
      } 
 
      else if (node.control && typeof (node.control.dispose) === "function") { 
 
       node.control.dispose(); 
 
      } 
 
      var behaviors = node._behaviors; 
 
      if (behaviors) { 
 
       behaviors = Array.apply(null, behaviors); 
 
       for (var k = behaviors.length - 1; k >= 0; k--) { 
 
        behaviors[k].dispose(); 
 
       } 
 
      } 
 
     } 
 
    } 
 
} 
 
    </script> 
 
</body> 
 
</html>

私が代わりにはなりませんでしたページ内のいくつかの既存のコードがあったことに注意してください。

これは私がしばらくの間苦労していたので、これは他の誰かに役立つことを願っています!

注: 私の場合、セッションはアライブ(SKA)クッキーはHTTP-だけではなかったので、私は、クライアント側からアクセスすることができた、唯一のクライアント側はいえください、ということに注意してくださいレポートサーバー自体の中にあります。 enter image description here

+1

新しいSQLサーバーバージョンを使用することがあります。 JavaScriptで設定できないCookieのブランドであるHTTP専用クッキーを使用する必要がありました。私は実際にこれを最初に試みました、そして、それは失敗しました。 SQL Server 2012 Reporting Services、バージョン11.0.5343.0に適用されます。 –

+0

はい、SKA CookieがHTTP専用ではないように見えるため、私はこのソリューションに頼っていました。私はHTTPSだけであるSSRSにホスティングサイトから渡しているカスタム認証クッキーを持っているので、キープアライブが異なっていたことに驚きました。 SSRS 2012バージョン11.0.2100.60も使用しています。違いがバージョンまたは異なる設定によるものかどうかは不明です。 – DicreetAndDiscrete

+0

これらの変更を行ったページはどれですか? C:\ Program Files \ Microsoft SQL Server \ MSRS13.MSSQLSERVER \ Reporting Services \ ReportServer \ Pagesの下にあるReportViewer.aspx? –

関連する問題