none
accesso pagine protette RRS feed

  • Domanda

  • ciao a tutti, cerco di essere il piu chiaro possibile:

    utilizzo una utility per la stampa delle pagina aspx in pdf e funziona alla grande (wkhtmltopdf.exe). questo eseguibile accetta n parametri, tra cui l'url della pagina ovviamente e il nome di un file su cui andrà a scriverne la versione in pdf.

    Ora, sulle pagine non protette tutto ok, sulle pagine con accesso tramite login (forms authentication) ovviamente non mi viene stampata la pagina in pdf, perche la richiesta fatta dall'eseguibile a sudetta pagina viene rifiutata e reindirizzata alla pagina di login (quella che poi effettivamente vedo nel pdf).

    ho provato ad aggirare il problema in questo modo:

    gestisco l'evento click del button che rappresenta l'avvio di stampa in pdf, eseguendo una richiesta con webclient.donwloadData, salvato il risultato e convertito in stringa in un file html di appoggio e ho passato proprio questo html al file eseguibile come argomento. (ho pensato che eseguendo la richiesta dal codebehind non sarebbe stata rifiutata) e invece l'esito è il medesimo.

    come posso risolvere il problema..?

    in che modo posso accedere dal codebehind all'url visualizzato dall'untete in quel momento e protetto?

    lunedì 6 settembre 2010 10:08

Risposte

  • Il GUID è un Globally Unique IDentifier. Si tratta di un codice generato automaticamente (una specie di Autonumber) che garantisce univocità globale. 

    Eccone un esempio: {265B9A8A-D8F2-414e-8C3B-19ADE7958E7A}

    In sostanza,

    1) Dalla pagina dove sei autenticato, dove vuoi generare il PDF, ti salvi a livello di database ad esempio, la richiesta (URL) dove vuoi andare autenticato, e associ a quella un GUID e una data di richiesta.

    2) Richiedi il download di un URL dove passi il tuo GUID ... tipo "trustedOperation.aspx?token=<GUID>"

    3) La pagina "TrustedOperation.aspx" dovrà accedere allo stesso database, verificare la data di richeista verso la data effettiva di scrittura del token (accetti la richiesta entro,diciamo, 10 secondi dalla creazione... 

    4) Se la verifica va a buon fine, sei un utente autorizzato al 99%.

    5) In ogni caso, alla prima richiesta di un GUID valido, lo rimuovi dal database.

    Parlo di database/tabella, puoui utilizzare anche l'Application come storage per una questione di scalabilità perchè riusciresti a far funzionare il tutto indipendentemente dal numero di web server o processi ASP.NET in esecuzione.

    Non è un sistema complesso, ma sufficientemente valido per garantire una sufficiente flessibilità e sicurezza nelle autenticazioni Trusted.

    HTH,

     


    Adriano
    mercoledì 8 settembre 2010 14:51

Tutte le risposte

  • Utilizzi il membership provider?
    LCO (congiuluc)
    lunedì 6 settembre 2010 10:42
    Moderatore
  • no, utilizzo il formsauthenticationticket e non posso modifcare la struttura.

    lunedì 6 settembre 2010 11:39
  • Potresti provare a crearti lato server l'authenticationTicket per esempio:

     Dim userData As String = "ApplicationSpecific data for this user."
    
       Dim ticket As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, _
        username, _
        DateTime.Now, _
        DateTime.Now.AddMinutes(30), _
        isPersistent, _
        userData, _
        FormsAuthentication.FormsCookiePath)
    
       ' Encrypt the ticket.
       Dim encTicket As String = FormsAuthentication.Encrypt(ticket)
    
       ' Create the cookie.
       Response.Cookies.Add(New HttpCookie(FormsAuthentication.FormsCookieName, encTicket))
    
       Response.Redirect("MyPage.aspx")
    
    

    Qui trovi della documentazione:

    http://msdn.microsoft.com/en-us/library/system.web.security.formsauthenticationticket.aspx

    http://msdn.microsoft.com/en-us/library/ff647070.aspx

    Ciao

     


    LCO (congiuluc)
    lunedì 6 settembre 2010 13:09
    Moderatore
  • e ci avevo pensato, ma come faccio a salvarlo sul server il ticket se eseguo il metodo response.cookies.add? in questo moodo il ticket va a finire sempre sul client dell'utente, non sul server dove risiedono le pagine aspx e da dove di fatto viene eseguita la richiesta della pagina.

    lunedì 6 settembre 2010 13:26
  • altri suggerimenti..?

    lunedì 6 settembre 2010 15:13
  • L'applicazione che usi se non sbaglio è un EXE non so bene come la esegui, la è un Out of Process, e come tale non puoi passare in maniera semplice un contesto da un processo all'altro...

    Tralasciando i dettagli... una soluzione potrebbe essere questa, in sostanza in "TRusted Login" con expiration:

    1) Ti salvi in sessione un GUID con la data di richiesta e l'utente che ha fatto richiesta... 

    2) Fai in modo che il tuo EXE lanci un URL con quel GUID su una pagina ben precisa

    3) La pagine non sarà sottoposta a FOrmsAuthentication, e andrà ad effettuare il login con le informazioni che ti sei salvato.

    4) Quando l'EXE farà richiesta di quella pagina risale tramite il GUID all'informazione in Cache/Sessione/Application/etc per capire se la richiesta avviene, per esempio, entro 1 minuto dall'effettiva richiesta... 

    5) DOpo la richiesta, rimuovi la riga dalla sessione dove ha salvato il GUID.

    In questo modo hai un URL dinamico (passi il GUID), discretamente sicuro ... entro 30 secondi e dopo la primanon sarà più utilizzabile da nessuno.

    HTT,

    Ciao,


    Adriano
    lunedì 6 settembre 2010 20:03
  • Grazie, ma è un pò troppo articolato il procedimento, la questione è almeno in apparenza più semplice:

    1) l'exe non esegue alcuna richiesta, questa viene fatta in modo indiretto. Come?

    Così:

    l'utente clicca sul bottone pdf, io gestisco l'evento click semplicemente facendo una richiesta webclient.downloadData al fine di salvare i dati in una pagina html d'appoggio (siatuata nella mia root).

    l'exe dunque, accederà a tale pagina html creata al runtime.

    Il problema non è l'accesso dell'exe a tale pagina (perche di fatto avviene e non ho problemi in questo).

    il problema si presenta quando all'interno del gestore evento click buttonPdf creo l'istanza di webClient, chiamo il metodo downloadData e tale metodo mi scarica i dati della pagina di login se la pagina che in realtà avrebbe dovuto scaricare è protetta dal formsauthentication.

    spero di essere stato piu chiaro.

    per cui ricapitolando, come posso risolvere?

     

    martedì 7 settembre 2010 13:15
  • Ciao! Ah ok allora la cosa probabilmente ha una soluzione più rapida. 

    Allora riprendendo la risposta di Congiuluc, correttamente dovresti creare un cookie per il FormsAuthenticationTicket, MA ovviamente non passarlo al Request, bensì al HttpWebRequest che esegue la tua richiesta:

    1) Creare un HttpWebRequest invece di un WebRequest tradizionale

    2) Creare un CookieContainer, aggiungere il tuo Cookie a questo container.

    3) Eseguire la tua richiesta lato server.

    Questo esempio tratto da MSDN dice come fare:

    http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.cookiecontainer.aspx

    Si usa questa strada anche per mantenere la sessione tra richieste successive, ad esempioq uando si fa Web-scraping,

    HTH,

    Ciao

     


    Adriano
    mercoledì 8 settembre 2010 08:21
  • non sono sicuro di aver ben capito, comunque non appena provo posto e vi faccio sapere. grazie
    mercoledì 8 settembre 2010 08:25
  • ho provato, ma non ho risolto nulla, questo è il codice:

     

    //test******************

     

    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "utente", DateTime.Now, DateTime.Now.AddMinutes(60), true, "ruolo");

     

    string encryptTicket = FormsAuthentication.Encrypt(ticket);

     

    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptTicket);

     

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(sourcePage.Request.Url.ToString());

    req.CookieContainer =

    new CookieContainer(1);

    req.CookieContainer.Add(

    new Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain));

     

    //*********************************

     

     

    //scrittura file html

     

    WebClient webClient = new WebClient();

    webClient.Headers.Add(

    "user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

     

    Byte[] PageHTMLBytes = webClient.DownloadData(sourcePage.Request.Url.ToString());

     

     

    UTF8Encoding encode = new UTF8Encoding();

     

    string txtPage = encode.GetString(PageHTMLBytes);

     

    StreamWriter sw = new StreamWriter(sourcePage.MapPath("~/PDF_Pages") + "\\pagina.html");

    sw.WriteLine(txtPage);

    sw.Close();

    mercoledì 8 settembre 2010 10:01
  • Ciao, devi utilizzare l'HttpWebRequest che hai preparato AL POSTO del WebClient per fare la richiesta, altrimenti il CookieContainer non serve a nessuno.

    WebClient è una classe semplificata che usa internamente l'HttpWebRequest, MA appunto perchè semplificata "maschera" il CookieContainer... quindi devi utilizzar l'HttpWebRequest per fare la richeista di download della tua pagina come da questo esempio:

    string ReadHtml (string address, string encoding) {
      Uri url = new Uri(address);
    
      CookieContainer cookieContainer = new CookieContainer();
    
    <strong>// qui metti il tuo codice per preparare il CookieContainer...</strong>
    
    
          HttpWebRequest httpWebRequest =   (HttpWebRequest)HttpWebRequest.Create(url);
      httpWebRequest.AllowAutoRedirect = true;
          httpWebRequest.KeepAlive  = true;
          httpWebRequest.CookieContainer = cookieContainer;
          httpWebRequest.UserAgent  = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
          httpWebRequest.Method  = "GET";
          HttpWebResponse webResponse = (HttpWebResponse)httpWebRequest.GetResponse();
    
      // Code Page
      Encoding enc = Encoding.GetEncoding(encoding); 
    
      // Read content
      StreamReader loResponseStream = new   StreamReader(webResponse.GetResponseStream(),enc);
      string  lcHtml  = loResponseStream.ReadToEnd();
    
      webResponse.Close();
      loResponseStream.Close();
    
      return lcHtml;
    
     }
    

    HTH,

    Ciao


    Adriano
    mercoledì 8 settembre 2010 10:30
  • Purtroppo ancora niente da fare..stesso identico risultato, questo il nuovo codice:

     

    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "utente", DateTime.Now, DateTime.Now.AddMinutes(60), true, "ruolo");

     

    string encryptTicket = FormsAuthentication.Encrypt(ticket);

     

    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptTicket);

     

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(sourcePage.Request.Url.ToString());

    req.CookieContainer =

    new CookieContainer(1);

    req.CookieContainer.Add(

    new Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain));

    req.AllowAutoRedirect =

    true;

    req.KeepAlive =

    true;

    req.UserAgent =

    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

    req.Method =

    "GET";

     

    HttpWebResponse webResponse = (HttpWebResponse)req.GetResponse();

     

    StreamReader loResponseStream = new StreamReader(webResponse.GetResponseStream());

     

    string lcHtml = loResponseStream.ReadToEnd();

    webResponse.Close();

    loResponseStream.Close();

     

    string txtPage = lcHtml;

     

    StreamWriter sw = new StreamWriter(sourcePage.MapPath("~/PDF_Pages") + "\\pagina.html");

    sw.WriteLine(txtPage);

    sw.Close();

    mercoledì 8 settembre 2010 11:12
  • Ok, verifica che :

    cookie.Domain 

    SIA l'effettivo dominio della tua applicazione; se è differente non funzionerebbe.

    Mi puoi dire l'URL della pagina a cui accedi... ovvero "SourcePage.Request.Url" ? Il "dominio" o "host" di quella pagina deve essere quello del Cookie.Domain. Se sono differenti è norlame che non funzioni...

    Ho trovato questo riferimento qui:

    http://bytes.com/topic/asp-net/answers/292117-httpwebrequest-posting-login-data

    HTH,
    Ciao


    Adriano
    mercoledì 8 settembre 2010 12:17
  • si, cookie.domain è corretto e sourcePage appartiene al dominio corretto (cioè allo stesso dominio di tutte le pagine dell'intero sito).

    facciamo in questo modo, tanto è una settimana che ci sto dietro e non ne vengo a capo: ritieni percorribile una strada tipo:

    se richiesta pagina protetta proviene da ip del server dove risiede iis, allora skip authorization.

    o è una cosa da evitare? non vedo altre alternative...

    mercoledì 8 settembre 2010 12:47
  • Ciao, 

    purtroppo non so dirti l'effettiva motivazione del tuo problema; se ci stai perdendo troppo tempo ti consiglio la strada del GUID che ti accennavo come prima soulzione sopra, ... è una strada semplice e gestibile... in quel modo hai una pseudo authentication, ma non lasciare "completamente libero" l'accesso alla pagina, non è il massimo... 

    CIAO!


    Adriano
    mercoledì 8 settembre 2010 12:54
  • allora per il momento ho risolto gestendo il gloabl.asax, (a giorni magari mi scrivo un modulo piu ad hoc).

    non faccio altro che verificare l'ip di chi ha eseguito la richiesta, se è l'ip del server, vuol dire che è il mio code behind ad eseguire la richiesta e quindi salto l'autenticazione.

    ovviamente, se qualcuno dovesse accedere al server, inserendo il path completo di qualsiasi pagina protetta acederebbe senza problemi..

    volendo seguire la strada del GUID (che non ho idea di cosa sia..), cosa dovrei effettivamente fare? (intanto cerco sul web guid :))

    mercoledì 8 settembre 2010 14:38
  • Il GUID è un Globally Unique IDentifier. Si tratta di un codice generato automaticamente (una specie di Autonumber) che garantisce univocità globale. 

    Eccone un esempio: {265B9A8A-D8F2-414e-8C3B-19ADE7958E7A}

    In sostanza,

    1) Dalla pagina dove sei autenticato, dove vuoi generare il PDF, ti salvi a livello di database ad esempio, la richiesta (URL) dove vuoi andare autenticato, e associ a quella un GUID e una data di richiesta.

    2) Richiedi il download di un URL dove passi il tuo GUID ... tipo "trustedOperation.aspx?token=<GUID>"

    3) La pagina "TrustedOperation.aspx" dovrà accedere allo stesso database, verificare la data di richeista verso la data effettiva di scrittura del token (accetti la richiesta entro,diciamo, 10 secondi dalla creazione... 

    4) Se la verifica va a buon fine, sei un utente autorizzato al 99%.

    5) In ogni caso, alla prima richiesta di un GUID valido, lo rimuovi dal database.

    Parlo di database/tabella, puoui utilizzare anche l'Application come storage per una questione di scalabilità perchè riusciresti a far funzionare il tutto indipendentemente dal numero di web server o processi ASP.NET in esecuzione.

    Non è un sistema complesso, ma sufficientemente valido per garantire una sufficiente flessibilità e sicurezza nelle autenticazioni Trusted.

    HTH,

     


    Adriano
    mercoledì 8 settembre 2010 14:51
  • ok, grazie mille.
    mercoledì 8 settembre 2010 15:02