2013. december havi bejegyzések

MSB4175: The task factory "CodeTaskFactory" could not be loaded

Az alábbi hibaüzenetbe sikerült belefutnom fordítás közben:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\CodeAnalysis\Microsoft.CodeAnalysis.targets(214,5): error MSB4175: The task factory "CodeTaskFactory" could not be loaded from the assembly "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll".

Could not load file or assembly ‘file:///C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll’ or one of its dependencies.

The system cannot find the file specified.

A dolog különlegessége, hogy a gépen csak VS 2013 volt, 2012 soha.

A problémát talán az okozza, hogy a 2013-as verziótól kezdve az MSBuild már nem a .NET Framework, hanem a Visual Studio része, ennek megfelelően a fájlrendszerben is máshol laknak a hozzá tartozó fájlok. A hibaüzenetből kiderült, hogy a Microsoft.Build.Tasks.v12.0.dll fájlt a rendszer a C:\Windows\Microsoft.NET\Framework64\v4.0.30319 mappában keresi, pedig nálam itt található: C:\Program Files (x86)\MSBuild\12.0\Bin. Átmásoltam, és azóta megy rendesen.

Valószínűleg nem ez a legszebb megoldás, de mivel a forráskódhoz nem lehetett hozzányúlni, és nálam megoldotta a problémát, nyugodtan alszom.

 

Technorati-címkék: ,,

Átirányítás a bejelentkező oldalra Ajaxnál

A hitelesítés korrekt megvalósításának egyik legproblémásabb része annak megoldása, hogy mi történjen akkor, ha az alkalmazáshoz a szükséges engedélyek nélküli kérések érkeznek. Ez így nagyon bénán hangzik, úgyhogy íme egy példa: a /admin URL-re bejelentkezés nélkül nem érkezhetnek kérések, sőt még azokat a kéréseket is el kell utasítani, amik bejelentkezett felhasználóhoz tartoznak, de a felhasználó nincs az Admins csoportban.

ASP.NET esetén szerencsére a FormsAuthenticationModule modul gondoskodik a probléma megoldásáról. Az OnLeave eseménykezelővel feliratkozik az EndRequest eseményre, és ha a HTTP státusz kód 401, akkor átirányítja a felhasználót a bejelentkező oldalra. Ez egy kiváló szolgáltatás hagyományos kérések esetén, de kifejezetten kellemetlen Ajaxnál.

Az átirányítás hatására ugyanis a kliens nem kapja meg a 401 Unauthorized hibát, hanem egy 302 Redirect fejléc fog visszajönni a szervertől, amit az XMLHttpRequest kliens oldalon az előírásnak megfelelően transzparens módon követ, azaz beküld egy kérést a Location fejlécben megadott útvonalra. Ez az útvonal tipikusan a Login.aspx oldalra mutat, aminek a szerver visszaküldi a HTML kódját, és ezt a HTML kódot fogja megkapni az XHR az Ajax hívás eredményeként 200 OK státusz kóddal. Ember legyen a talpán, aki ezt a helyzetet kliens oldalon értelmesen kezelni tudja.

Sajnos .NET 4.0-ig nem volt más megoldás a probléma kezelésére, mint egy saját HTTP modul beillesztése az ASP.NET csővezetékbe. Az ASP.NET 4.5 azonban bevezetett egy új lehetőséget a HttpResponse.SuppressFormsAuthenticationRedirect tulajdonság formájában, amit true értékre állítva elkerülhető az átirányítás, és helyette az eredeti 401-es hibakódot fogja megkapni a kliens. Mivel ez a tulajdonság a Response része, ezért nem tudjuk globálisan beállítani, hanem minden olyan kérésnél be kell billenteni, ahol el akarjuk kerülni az átirányítást. Ha esetleg minden kérésnél így akarunk eljárni, akkor tehetjük ezt a tulajdonság állítást a global.asax fájlban lévő Application_EndRequest eseménykezelőbe.

Miután a kliens megkapja az egyértelmű hibakódot, JavaScriptből már úgy járhatunk el, ahogy az igényeink megkívánják, például feldobhatunk egy hibaüzenetet vagy egy bejelentkező ablakot. De ez a kód már eddig is megvolt, nem igaz?

 

Technorati-címkék: ,,

Mennyire egyedi a machine key?

Az ASP.NET platform számos kriptográfiai funkciója épül a machine key-re, épp ezért különösen fontos, hogy az egymástól független alkalmazásokhoz egyedi machine key tartozzon. Szerencsére az alapbeállítás szerint látszólag minden alkalmazás egyedi kulcsot kap:

<machineKey validationKey="AutoGenerate,IsolateApps" 
decryptionKey="AutoGenerate,IsolateApps" />

Az AutoGenerate beállítás hatására a platform automatikusan generál kulcsot, az IsolateApps-nak köszönhetően pedig elvileg ezek a kulcsok alkalmazásonként egyediek lesznek.

De nem mindig!

Az ASP.NET valóban generál automatikusan kulcsot, csakhogy nem a validation key-t és a decryption key-t, hanem egy ős kulcsot (hívhatjuk ezt általánosan machine key-nek), amiből azután transzformációkkal áll elő a két kulcs.

A machine key-t  platform a registry-ben tárolja, a következő útvonalon:

HKCU\Software\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeyV4

Érdemes észrevenni, hogy a tárolás a HKEY_CURRENT_USER hive-ban történik, azaz a generált machine key az adott felhasználó profiljához fog tartozni! Ebből logikusan következik, hogy ha az IIS-ben két alkalmazás ugyanannak a felhasználónak a nevében fut, akkor azonos machine key-t fognak használni! Íme egy újabb ok, hogy miért kell elfelejteni a SYSTEM, LOCAL SERVICE és NETWORK SERVICE felhasználókat, és miért kell helyettük önálló ApplicationPoolIdentity-vel futtatni minden egyes alkalmazást. Ebből is látszik, hogy az application pool az alkalmazások izolációjának eszköze.

Az, hogy két alkalmazásnak ugyanaz az ős kulcsa, még nem feltétlenül jelent problémát, hiszen tudjuk, hogy a két valóban használt kulcs transzformációkkal áll elő. Ezt a transzformációt határozza meg az AutoGenerate utáni módosító. Az IsolateApps hatására a transzformációba bekerül a HttpRuntime.AppDomainAppVirtualPath tulajdonság értéke, ami egy website-on belül, két különböző virtuális mappában ülő alkalmazás esetén eltérő lesz, így a két generált kulcs is el fog térni (pont ez a cél).

Ám nem fog eltérni abban az esetben, ha a két alkalmazás ugyanazon az útvonalon van, de eltérő webhelyeken. Például a gyökérben ülő alkalmazásnál ennek a tulajdonságnak az értéke mindkét esetben “/” lesz, azaz az IsolateApps egyáltalán nem teszi meg azt, amit várunk tőle!

Ilyen esetekre került az ASP.NET 4.5 be az IsolateByAppId módosító, ami nem a HttpRuntime.AppDomainAppVirtualPath, hanem AppDomainAppId tulajdonság felhasználásával készíti a két kulcsot. Ennek az értéke valami ilyesmi: 

/LM/W3SVC/3/ROOT 

A közepén a “3” az én esetemben a website azonosítója az IIS-ben, a “ROOT” pedig azt jelenti, hogy a site gyökerében van az alkalmazás.

Összegezve tehát: az alap AutoGenerate,IsolateApps beállítás nem minden esetben eredményez egyedi kulcsot, de ha az alkalmazásokat saját application poolba tesszük és azokat ApplicationPooldentity-vel futtatjuk, valamint az IsolateApps helyett az IsolateByAppId módosítót használjuk, akkor már nem biztosan egyedi kulcsokat fognak kapni az alkalmazásaink.

Ha nem hiszed, legegyszerűbben úgy járhatsz utána, hogy a localtest.me domain segítségével létrehozol két webhelyet az IIS-ben, majd azokon létrehozol két alkalmazást, ami például Milan Negovan kódja segítségével kiírja a kulcsokat.

 

Technorati-címkék: ,,

Az IIS Express mindig újraindul

A Visual Studio 2013-mal telepített IIS Express használata közben feltűnhet, hogy a korábbi verziókkal ellentétben a debuggolás végén mindig leáll a webszerver. Ez annak köszönhető, hogy a Visual Studio 2013-tól kezdve nem csak hogy van Edit and Continue támogatás 64-biten, de most már ez alapból be is van kapcsolva web alkalmazások esetén:

iis-express-edit-and-continue

Ha erre nincs szükségünk és kikapcsoljuk, akkor nem fog leállni az IIS Express.

 

Technorati-címkék: ,

Az IIS Express kitakarítása

Az IIS Express a beállításait a %USERPROFILE%\Documents\IISExpress\config\applicationHost.config fájlban tárolja, ami nagyon kényelmes, hiszen így nem szükséges rendszergazdai jog a szerkesztéséhez. Ennek következménye, hogy a Visual Studio eltávolításával a webszerver és a webalkalmazások beállításai megmaradnak.

Előfordulhat, hogy eltávolítjuk a VS 2012-t, telepítjük a 2013-as verziót, majd létrehozunk egy új webalkalmazást, ami szokatlanul viselkedik, például minden indításakor Windowsos bejelentkezést kér. Ez lehet amiatt is, hogy a korábban már hoztunk létre ugyanilyen néven webhelyet az IIS Expressben, aminek a beállításai megőrződtek a konfigurációs fájlban.

Ha a szokásos projektjeink mellett gyakran hozunk létre tesztelésre webprojekteket, akkor időnként érdemes kitakarítani az IIS Expresst. Mivel nincsen hozzá grafikus felületünk, vagy kézzel szerkesztjük az applicationHost.config fájlt, vagy parancssorból esünk neki.

Az Expresses appcmd.exe a C:\Program Files (x86)\IIS Express mappában található. Listázhatjuk vele a webhelyeket:

C:\Program Files (x86)\IIS Express>appcmd list site
SITE "WebSite1" (id:1,bindings:http/:8080:localhost,state:Unknown)
SITE "MyProject" (id:2,bindings:http/*:44441:localhost,https/*:44300:localhost,state:Unknown)
SITE "WebSite1(1)" (id:3,bindings:http/*:44468:localhost,state:Unknown)
SITE "WebSite2" (id:4,bindings:http/*:44465:localhost,state:Unknown)

Ha a webhelyek nevei nem mondanak sokat, akkor listázhatjuk a virtuális mappákat, mert azok mellett megjelennek a fizikai útvonalak is:

C:\Program Files (x86)\IIS Express>appcmd list vdir
VDIR "WebSite1/" (physicalPath:%IIS_SITES_HOME%\WebSite1)
VDIR "MyProject/" (physicalPath:W:\Projektek\MyProject)
VDIR "WebSite1(1)/" (physicalPath:W:\Temp\WebSite1)
VDIR "WebSite2/" (physicalPath:W:\Desktop\WebSite2)

Ha valamelyik webhelyre még szükségünk van, csak épp értelmes nevet akarunk neki adni, akkor átnevezhetjük:

C:\Program Files (x86)\IIS Express>appcmd set site WebSite1(1) -name:Master
SITE object "WebSite1(1)" changed

Amire pedig nincs szükség, azt bátran törölhetjük:

C:\Program Files (x86)\IIS Express>appcmd delete site WebSite2
SITE object "WebSite2" deleted

 

Technorati-címkék: ,,

Árulkodó HTTP fejlécek eltávolítása

Ha megnézzük egy ASP.NET alkalmazásunk hálózati forgalmát, akkor könnyen felfedezhetjük az alábbi fejléceket a HTTP válaszban:

Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 5.0

Ezek a fejléc mezők egyáltalán nem befolyásolják az alkalmazás működését, az egyetlen céljuk, hogy a Bing bot több információt nyerjen a webhelyről.

Sajnos azonban ezek a fejlécek a támadók dolgát jelentősen megkönnyítik, hiszen ha pontosan ismert a platform és a verziószám, akkor már elég csak azokkal az támadásokkal próbálkozni, amik ebben a környezetben működnek. Éppen ezért biztonsági okokból célszerű megváltoztatni az alapbeállításokat és eltávolítani ezeket a fejléceket.

 

Server

A Server fejléc “sugárzása” bele van drótozva az IIS-be, én nem tudok olyan kapcsolóról, amivel kényelmesen kikapcsolható lenne. Lehet használni az UrlScant, bár az az eszköz utoljára 2008-ban frissült. Ha ASP.NET alkalmazásunk van, akkor a global.asax-ban leszedhetjük ezt a fejléc mezőt, mielőtt a HTTP válasz kimenne a szerverről:

protected void Application_PreSendRequestHeaders()
{
  this.Response.Headers.Remove( "Server" ); }

 

X-Powered-By

Az X-Powered-By fejlécet az IIS pakolja rá a HTTP válaszokra, így akár szerver szinten megszabadulhatunk tőle az IIS Managerben:

header-x-powered-by

 

Vagy akár web.configban is:

<system.webServer>
   <httpProtocol>
     <customHeaders>
       <remove name="X-Powered-By" />
     </customHeaders>
   </httpProtocol>
</system.webServer>

 

X-AspNet-Version

Az X-AspNet-Version fejlécet viszonylag egyszerű kikapcsolni a web.configban:

<httpRuntime enableVersionHeader="false" />

 

X-AspNetMvc-Version

Az X-AspNet-Version fejlécet az alkalmazásunk indulásakor kapcsolhatjuk ki:

protected void Application_Start()
{
MvcHandler.DisableMvcResponseHeader = true; }

 

Ha mindezeket a beállításokat egyszerűbben szeretnénk elvégezni, akkor támaszkodhatunk a CodePlexen ingyenesen elérhető NWebsec projektre, amely a konfiguráció szigorításán kívül további lehetőségeket nyújt MVC-s és Azure-os projektek számára, illetve a session kezelés biztonságosabbá tételére. Ezek a funkciók egymástól függetlenül, önállóan is elérhetők NuGet csomagok formájában.

 

Technorati-címkék: ,,