S'authentifier en POST avec un WebClient

icon Tags de l'article : ,

Aout 09, 2016
Hello,

Lorsqu'on est comme moi, on a tendance à aimer faire des tools qui vont scraper des pages web à l'aide d'un WebClient C#.

Sauf que voilà, il faut parfois pouvoir s'authentifier pour accéder à des pages qu'on aimerait parser... Et pour ça. Il y a une solution ! :)

Déjà, il va vous falloir une classe dérivée de WebClient qui gère les cookies et l'authentification :

// source : http://stackoverflow.com/questions/11118712/webclient-accessing-page-with-credentials
public class CookieAwareWebClient : WebClient
{
    public CookieAwareWebClient()
    {
        CookieContainer = new CookieContainer();
    }
    public CookieContainer CookieContainer { get; private set; }

    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = (HttpWebRequest)base.GetWebRequest(address);
        request.CookieContainer = CookieContainer;
        return request;
    }
}

Maintenant, vous n'avez plus qu'à utiliser cette classe pour vous authentifier avec un UploadValues (en lui passant vos paramètres POST) :

using (var client = new CookieAwareWebClient())
{                
    // on spécifie que c'est du POST
    client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

    // cette ligne est ajoutée car parfois les authentifications vérifient le referer
    client.Headers.Add("Referer", "https://referer/if/needed");

    // on crée notre table clef / valeur
    var values = new NameValueCollection
    {
        { "username", "us3rn4me" },
        { "password", "p4ssw0rd" }
    };

    // on s'authentifie
    client.UploadValues("https://url/de/la/page/d/authentification", values);

    // et voilà, on n'a plus qu'à appeler les pages qui nous intéressent, accessibles désormais vu qu'on s'est authentifiés avec le UploadValues !
    var pageContent = client.DownloadString(url);
}

Et le tour est joué !

Bon dev à tous !

Modifier ses AppSettings et ConnectionStrings via les fichiers de config en .Net

icon Tags de l'article : , , ,

Juin 24, 2016
Hello,

Petit article, ça faisait longtemps :)

Aujourd'hui on va parler .Net, AppSettings et ConnectionStrings.

Lorsqu'on développe, la bonne pratique est d'utiliser les fichiers de configuration pour stocker nos paramètres d'application et nos chaines de connexion. Ce fichier de configuration s'appelle, pour ceux qui ne le savent pas, Web.Config ou App.Config. Exemple :

<appSettings>
     <add key="MyValue" value="42"/>
     <add key="MyIPAddress" value="::1"/>
</appSettings>
<connectionStrings>
     <add name="MyConnectionString" connectionString="Data Source=.\;Initial Catalog=MyDB;Persist Security Info=True;User ID=MyLogin;Password=MyPassword;MultipleActiveResultSets=True" />
</connectionStrings>

Classique vous me direz. Maintenant, savez vous comment faire pour que les valeurs de vos AppSettings et ConnectionStrings changent lorsque vous publiez en mode Release ?

Et oui, il faut modifier le fichier Web.Release.Config (ou App.Release.Config).

Dans ce fichier, vous pouvez ajouter de nouveaux AppSettings ou ConnectionStrings, mais vous pouvez aussi modifier les valeurs par défaut (du Web.config ou App.config)

Voici un exemple qui va :
  • Supprimer l'AppSettings MyValue
  • Modifier la valeur de l'AppSettings MyIPAddress
  • Modifier la valeur de la ConnectionString MyConnectionString

<appSettings>
     <add key="MyValue" xdt:Transform="Remove" xdt:Locator="Match(key)"/>
     <add key="MyIPAddress" value="1.2.3.4" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
<connectionStrings>
     <add name="MyConnectionString" connectionString="Server=tcp:myserver.database.windows.net,1433;Database=mydb;User ID=mylogin@mydb;Password=mypassword;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>

Simple non ?

En résumé, lors de la publication dans une config sélectionnée (debug, release ou autre) :
  • Supprimer une ligne: xdt:Transform="Remove" xdt:Locator="Match(key)"
  • Modifier la valeur d'une ligne : xdt:Transform="SetAttributes" xdt:Locator="Match(key)"
  • Ajouter une ligne : il suffit de l'ajouter dans le fichier concerné

Une dernière chose, non négligeable : ces modifications / suppressions n'impacteront pas votre application lorsque vous la lancez en local, même dans la configuration sélectionnée ! Pour ça, il faut faire les modifications à la main dans le web.config ou app.config.

Bon dev à tous !

Le célèbre bug du cookie ASP.Net qui disparait

icon Tags de l'article : , ,

Septembre 18, 2015
Tout le monde se fait avoir, et ça vient de m'arriver.

Alors que je développais tranquillement ma solution, je me suis rendu compte que ma connexion à l'application cassait juste après que je me sois connecté.

Après vérification, il s'avérait que mon cookie disparaissait sans raison dès que je faisais la moindre action après ma connexion.

J'ai tout vérifié, mon code de création de cookie était bon :

Response.Cookies["UserSettings"]["IdUser"] = user.Id.ToString();
Response.Cookies["UserSettings"]["Token"] = user.Token;
Response.Cookies["UserSettings"]["Name"] = user.FirstName + " " + user.LastName;

Response.Cookies["UserSettings"].Expires = DateTime.UtcNow.AddDays(WebAppConstants.COOKIE_LIFETIME);

D'où ça vient ? C'est très simple : je devais probablement faire un Response.Cookies à un endroit au lieu d'un Request.Cookies pour lire le contenu de mon cookie.

Et effectivement c'était le cas, à un endroit où j'essayais de lire mon cookie :
if(Response.Cookies["UserSettings"] != null && Response.Cookies["UserSettings"]["Name"] != null) 
{
     //...
}

En effet, en ASP.Net, dès qu'on essaie de lire un cookie avec Response.Cookies, un cookie qui sera automatiquement renvoyé au navigateur est créé.

Or comme on ne spécifie pas la date d'expiration du cookie... il s'agit du 01/01/0001. Et du coup, quand le navigateur recevra ce cookie, il se dira que son cookie existant est obsolète... et le supprimera.

Donc rappelez-vous en : dès qu'un cookie disparait sans raison après avoir été créé, il y a de fortes chances que vous ayez essayé d'y accéder en passant par Response.Cookies au lieu de Request.Cookies !