12
votes

SSRS: Pourquoi les ska-cookies s'accumulent-ils jusqu'à "HTTP 400 Mauvaise demande - la demande trop longue" se produit?

J'ai commuté des services de reporting SQL-Server 2012 (SSRS 2012) à l'authentification des formulaires afin que nous puissions l'utiliser sur Internet.

Je n'ai pas pu trouver un échantillon de formulaires-authentification pour SSRS 2012 N'importe où, donc je devais prendre le SSRS 2008R2 ONE, et l'adaptez-le pour 2012, pour une connexion unique (SSO). P>

À ce stade, tout semblait fonctionner comme prévu; J'ai même réussi à obtenir SSO travaillant à travers les domaines. P>

mais maintenant j'ai un problème: p>

Je testais tous les rapports (plus de 200) avec Google Chrome, car je devais insérer Un peu de JavaScript qui modifie la taille de la bordure TD pour que le HTML s'affiche directement dans Non-IS5-QuirksMode. Après environ le 50e rapport, j'ai soudainement obtenu: p>

"HTTP 400 mauvaise demande - Demande trop longue" P>

Après cela, je ne pouvais pas voir aucun autre rapport, pas même ceux qui ont fait Travailler auparavant. P>

Le problème semble être causé par trop de biscuits et, en effet, lorsque j'ai supprimé quelques "* _ska" (session me tenir en vie?) Cookies, il a commencé à travailler à nouveau. P>

SSRS suce p>

Mon problème maintenant est que je ne sais pas quelles causes Ce "débordement de biscuits". Je ne sais pas non plus, si cela est un bogue en chrome, un bug de la Vanilla SSRS ou un bug causé par la nouvelle authentification des formulaires. P>

Tout ce que je fais dans la nouvelle authentification des formulaires qui a quelque chose à faire Avec des cookies, c'est ceci: p> xxx pré>

et car ce code crée "SQLAUTHOCKIE" que l'on voit en bas. Il n'y a qu'une seule "sqlauthcookie" donc je ne pense pas que cela puisse être un bug de formes-authentification. P>

Le problème semble être les cookies SKA, que Afaik n'a rien à voir avec les formes-authentification et tout à voir avec la vanille SSRS. P>

La seule autre chose que je pouvais voir comme une raison pour cela est la modification du délai d'attente d'authentification-authentification à 720 minutes à 720 minutes dans la section Formulaires-authentification de Le fichier web.config. p>

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


0 commentaires

3 Réponses :


8
votes

problème répertorié comme fixe fort> SQL Server 2012 SP1 Cu7. strong> (voir les commentaires de Microsoft dans Connect Numéro )
Mais toujours présent dans SQL-Server 2014.


La section ultérieure s'applique, si vous ne pouvez pas installer SQL Server 2012 SP1 CU7: P>

OK, a obtenu la réponse moi-même. P>

Le cookie Keep-Alive est émis chaque fois que l'on ouvre un rapport.
Maintenant, cela devient un problème lorsque l'on s'ouvre (ou actualise ou modifie une autre page), disons, plus de 110 à 120 rapports, sans fermer le navigateur. P>

Nous sauvegons-nous en supprimant les cookies en excès, et définir une limite de sécurité sur Appx. 1/2 du maximum supposé 120 biscuits. P>

Les cookies sont httponly et expirent quand on ferme le navigateur (cookies de session).
Ils sont des cookies httponly non sécurisés, c'est pourquoi j'ai échoué dans ma tentative de les supprimer via JavaScript.
Il devient donc nécessaire de les supprimer du côté serveur. Étant donné que nous ne pouvons pas modifier reporterver, nous devons utiliser des scripts en ligne. P>

<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">


8 commentaires

La fermeture du navigateur n'a pas fonctionné pour moi avec chrome. J'ai dû supprimer manuellement les cookies. Je vais essayer votre solution latérale du serveur bientôt. Merci!


Cela n'a pas fonctionné pour moi avant d'avoir changé c.path = demande.applicationPath + "/ pages"; à c.path = demande.ca.path [I] .Path;


@Masty: drôle, demande.cookies [i] .Path ne fonctionne pas pour moi. Non plus c.path = demande.cokies [i] .Path + "/ pages"; Avez-vous installé ServicePack 1 + les dernières mises à jour cumulatives?


J'ai vérifié et le problème est vraiment corrigé dans SQL Server 2012 SP1 CU7.


J'ai ajouté une question sur la question liée à Microsoft Connect, mais je me demande si quelqu'un sait si ce problème existe dans SQL Server 2014 et, dans l'affirmative, quelle mise à jour ou quel service le corrige.


@Paul Karlin: Oui, il existe également dans SQL-Server 2014 et il n'est pas corrigé. Il y a le 1er service de service, mais notre administrateur ne l'a pas trouvé, pourtant, je ne peux donc pas dire si le service Pack corrige ce problème.


J'ai essayé de mettre à jour la page ReportViewer.aspx avec le code que vous avez mentionné ci-dessus mais pas de chance.


@Stefansteiger Je reçois toujours cette erreur même après avoir apporté des changements comme vous l'avez suggéré.



6
votes

3 commentaires

Belle trouvaille. Je vais essayer ça.


FYI, si vous utilisez le rapport de rapport "standard", ce paramètre peut être modifié dans Reporting Services \ RAPPORTERVER \ PAGES \ REPORTVIEWER.ASPX en ajoutant KeepSessionalive = "False" à la balise RS: ReportViewerHost.


@graham Mendick: D'autre part, si vous faites cela, vous obtiendrez un message d'erreur de session expiré si vous cliquez sur Exporter après 5 à 10 minutes d'inactivité.



4
votes

J'avais beaucoup de difficulté à mettre en œuvre différentes solutions à ce problème à cause de l'architecture de notre site - pour une raison quelconque, mes collègues avaient décidé à l'origine d'utiliser des iframes avec des liens vers les rapports au lieu d'un contrôle de reportageViewer et j'étais détesté à Essayez de changer cela si tard dans le processus de développement en raison d'une simple question de cookie.

Solutions J'ai essayé que n'a pas fort> travail: p>

  1. implémentation Stefan Stefan Stefan Stefan Stefan "Stefan " STEFAN strong> - le code du serveur sur mon La page n'a pas pu accéder aux cookies définis dans le document IFrame intégré LI>
  2. Changer de biscuits du document parent en JavaScript STROND> - Pour des raisons de sécurité compréhensibles, je n'ai pas pu accéder aux cookies dans l'IFrame du code côté client, soit LI>
  3. a essayé de passer des paramètres dans l'URL du rapport pour le dire de ne pas conserver la session en vie forte> - Essayé Ajementif "& RS: GarderieLive = Faux", ce qui n'a pas provoqué d'erreur, mais n'a pas fonctionné li>
  4. * joué * avec l'idée d'injecter JavaScript dans les rapports eux-mêmes strong> - Considérant que cela impliquerait de modifier certaines rapports et de la fonctionnalité des rapports exportés / sauvegardés , ce n'était pas une option li> ol>

    Enfin, après piquer autour du serveur, j'ai réalisé que le dossier (Fichiers PAGES "(FIXT> (C: \ Program Files \ Microsoft SQL Server \ MSRS11.SQXXPRESS \ SERVICES SERVICES \ Reporterver \ pages) contenait un document "ReportViewer.aspx" strong>. P>

    Et que savez-vous? C'est juste une simple page ASP.NET avec un en-tête où vous pouvez ajouter votre propre JavaScript!? strong> p>

    Alors, voici Strong> Qu'est-ce qui a travaillé pour moi: strong> p>

    Je viens d'ajouter le Code de réglage de la cookie latérale J'avais trouvé ailleurs ci-dessous pour supprimer tous les cookies de la page ReportViewer, et tout a soudainement travaillé! Un seul cookie de maintien à la fois! P>

    p>

    <%@ 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));
    	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>


4 commentaires

Vous pouvez utiliser une nouvelle version SQL-Server. Je devais utiliser des cookies HTTP uniquement, une marque de cookies que vous ne pouvez pas définir avec JavaScript. J'ai effectivement essayé cela en premier et cela a échoué. Ils auraient peut-être changé de mise en œuvre.My Code s'applique à SQL-Server 2012 Reportingservices, version 11.0.5343.0.


Oui, je n'ai recours à cette solution que parce que les cookies SKA semblaient ne pas être http-seulement. J'ai un cookie d'authentification personnalisé, je passe du site d'hébergement à la SSRS, qui est HTTP-seulement, alors j'ai été surpris de voir que les conservateurs étaient différents. J'utilise également SSRS 2012, version 11.0.2100.60. Je ne sais pas si la différence est due à la version ou à une configuration différente.


Quelle page vous apportez ces changements? ReportViewer.aspx qui vit sous C: \ Program Files \ Microsoft SQL Server \ msrs13.msqlServer \ Significing Services \ SignesServer \ pages par exemple?


@Vivek Patel: Oui, exactement cela, à moins que vous n'ayez encore une autre instance nommée de SSRS.