BigBastis Blog About Me & my Digital Lifestyle

15Mrz/130

Clover: Tabs für den Windows Explorer

clover_screenshot

Ich glaube schon seit Windows 98 habe ich mich gefragt, warum Microsoft dem Windows Explorer keine Tabs spendiert. Auch Apple bekommt es unter Mac OS nicht hin den Finder Tab-Fähig zu machen. Warum eigentlich nicht?

Clover zeigt wie es gehen könnte. Dieses einfache kleine Tool kombiniert alle Windows Explorer Fenster unter einem Dach und lässt sich dabei so flüssig bedienen, dass es schon fast wie eine native Lösung wirkt.

Auf den ersten Blick fällt sofort auf, dass hier einige Teile vom Google Chrome eingeflossen sind. So gleicht das Look and Feel der Tabs und auch deren Bedienung bis ins Detail dem von Chrome. Alles ist super Flüssig und funktioniert komplett ohne Konfiguration sofort so wie man es gewohnt ist.

So lassen sich neue Tabs mit STRG+T öffnen und mit STRG+TAB durchschalten. Mit einem Doppelklick während man die STRG-Taste gedrückt hält wird der gewählte Ordner in einem neuen Tab geöffnet. Die Tabs selbst integrieren sich in die Titelleiste des Fensters und verbrauchen so gut wie keinen Platz.

Optional kann man auch noch (wie auch im Chrome) eine Lesezeichenleiste einblenden lassen, in der man seine Lieblingsordner speichern kann. Ich finde aber, dass es die Optik etwas stört.

Das Icon des Programms könnt ihr ebenfalls verändern, wenn euch das Kleeblatt nicht zusagt. Eine Anleitung dafür gibts auf der Homepage des Entwicklers.

Weitere Infos und Download.

29Jan/130

Nice 2 Know: Razor ViewEngine ausserhalb von MVC nutzen

Wenn ihr ASP.NET MVC ab Version 3 schon mal benutzt habt dann wird euch die Razor ViwEngine kein Fremdword mehr sein. Oft kommt man aber gar nicht drauf, dass man diese praktische Templating-Engine auch außerhalb von MVC benutzen kann.

So kann man dieses Feature super gebrauchen wenn die App E-Mails versenden soll und man größere E-Mail Templates nutzen will. Das Schöne an der Razor Engine ist, dass man diese sehr einfach integrieren kann und der Code sehr verständlich und sauber bleibt.

Die Installation erfolgt hier wie so oft sehr einfach über NuGet:

Jetzt ist man im Grunde schon fertig und kann sofort loslegen. Starten wir mit dem Model, das die Razor Engine für uns verarbeiten wird. Dies ist eine gewöhnliche Klasse (POCO):


public class TipReminder
{
	public string DisplayName { get; set; }

	public string EmailAdress { get; set; }

	public DateTime LastLogin { get; set; }
}

Jetzt legen wir uns ein kleines Template an, das den Inhalt der Email darstellen soll:


@model Projekt.Domain.AppUser
<!DOCTYPE html>

<head>
    <meta name="viewport" content="width=device-width" />
    <title>Newsletter</title>
</head>
<body>
    <div>
        <h2>Hallo @Model.DisplayName</h2>
        <p>Es ist wieder Zeit für einen Newsletter</p>
        <p>Dein letzter Login war am @Model.LastLogin - das ist schon lange her!</p>
        <p>Schau doch mal wieder vorbei.</p>
        <hr />
        <p>Bitte antworten Sie nicht auf diese EMail</p>
        <p>Viel Spaß weiterhin!</p>
    </div>
</body>
</html>

Man beachte hier besonders die Zeilen 10 und 12 wo wir auf das Model zugreifen.

Wenn ihr ASP.NET MVC 3 oder 4 schon mal genutzt habt, werdet ihr feststellen, dass alles exakt der Syntax einer View gleicht, sogar die Definition der strickten Typisierung auf das Model oben.

Die eigentliche Nutzung ist dann ein Kinderspiel:


foreach (AppUser user in db.Users)
{
    string renderedEmail = Razor.Parse(File.ReadAllText(pathToEmailTemplate), user);
    EMailHelper.SendEmail(renderedEmail, user.EmailAdress);
}

Wirklich interessant ist hier nur Zeile 3 wo wir den eigentlichen Aufruf an die RazorEngine tätigen. Die Parse-methode benötigt lediglich das Template als String und ein Model zur Verarbeitung.

Das ist ein wirklich praktisches Feature um die Templates auf einfachste Weise aus dem Programm herauszulösen. Das Ganze ist nicht neu (gibt’s schon seit fast 2 Jahren) man muss nur wissen, dass es möglich ist. :-)

8Okt/122

ASP.NET MVC: Aktuellen Menülink hervorheben

Dieses "Problem" müsste eigentlich jeder kennen der schon mein eine Webseite mit mehreren Bereichen erstellt hat. Wie kann ich den Menüpunkt der aktuell angezeigten Seite hervorheben?

Hier gibt es viele Ansätze. Ich hatte schon Seiten, die die CSS Klassen ins HTML hardcoden, irgendwelche anderen Schandtaten betreiben oder nicht wirklich schöne If-Abfragen um die Menüpunkte legen.


            <li @if (activeMenu.Equals("Home"))
                {
                    <text>class="active"</text>
                }>@Html.ActionLink("Home", "index", "home")</li>

Hier muss man natürlich noch bedenken, dass ein entsprechender ViewBag-Eintrag namens "activeMenu" in jeder Action gesetzt werden muss. urgs

Ich möchte diese ganze Logik nicht in den Views haben. Daher habe ich eine kleine ExtensionMethot für den HtmlHelper geschrieben.

Diese Extension generiert für mich die Menülinks und prüft beim Generieren des Links ob das Ziel des Links mit dem aktuellen Controller und der aktuellen View übereinstimmt. Wenn das der Fall ist wird dieser Link als aktiv markiert. So sieht das Ganze aus:


public static MvcHtmlString NavigationActionLink(
    this HtmlHelper htmlHelper, string linkText,
    string actionName, string controllerName, object routeValues = null,
    object htmlAttributes = null, 
    string wrapperElement = "li", string flag = "active")
{
    var generatedLink = HtmlHelper.GenerateLink(
                    htmlHelper.ViewContext.RequestContext,
                    htmlHelper.RouteCollection, linkText,
                    (string)null, actionName, controllerName,
                    new RouteValueDictionary(routeValues), 
                    (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));

    var wrappedElement = WrapGeneratedLink(
                    htmlHelper, actionName, 
                    controllerName, wrapperElement, flag, generatedLink);

    return MvcHtmlString.Create(wrappedElement.ToString(TagRenderMode.Normal));
}

private static TagBuilder WrapGeneratedLink(
    HtmlHelper htmlHelper, string actionName, string controllerName,
    string wrapper, string flag, string generatedLink)
{
    var wrapperElement = new TagBuilder(wrapper)
                                {
                                    InnerHtml = generatedLink
                                };

    if (CurrentRouteMatchesGeneratedUrl(actionName, controllerName, htmlHelper))
    {
        wrapperElement.AddCssClass(flag);
    }
    return wrapperElement;
}

private static bool CurrentRouteMatchesGeneratedUrl(
    string actionName, string controllerName, HtmlHelper htmlHelper)
{
    var currentAction = (string)htmlHelper.ViewContext.RouteData.Values["action"];
    var currentController = (string)htmlHelper.ViewContext.RouteData.Values["controller"];

    return string.Equals(currentAction, actionName, 
                        StringComparison.CurrentCultureIgnoreCase) &amp;&amp;
            string.Equals(currentController, controllerName, 
                        StringComparison.CurrentCultureIgnoreCase);
}

Hier der Code nochmal etwas schöner formatiert.

Dieser Helper orientiert sich an dem gewöhnlichen ActionLink und hat die gleichen Parameter bis auf die letzten zwei, mit denen man bestimmen kann wie der Link hervorgehoben werden soll.

So könnte man nun die Menülinks verwenden am Beispiel Twitter Bootstrap:


<div class="navbar navbar-inverse navbar-fixed-top">
    <div class="navbar-inner">
        <div class="container">
            <div class="nav-collapse">
                <ul class="nav">
                @Html.NavigationActionLink("meinlink", "index", "home")
                @Html.NavigationActionLink("meinlink", "index", "account", null, null, "div", "selected")
                </ul>
            </div>
        </div>
    </div>
</div>    

So würde der erste Link folgendes generieren:


<li class="active"><a href="/">meinlink</a></li>

Und der zweite Link das hier:


<div class="selected"><a href="/">meinlink</a></div>

Auf diese Weise kann mann etwas Einfluss darauf nehmen was da generiert wird und mit welcher Klasse das erzeugte Feld markiert wird.

Der zweite Link macht natürlich keinen Sinn in dem Twitter Bootstrap Beispiel und wurde nur zu Demonstrationszwecken genutzt :)

So entfernt man den hässlichen Code aus den Views und muss sich darum keinen Kopf mehr machen.

Übrigens: In dem meisten Fällen reicht es wenn man nur nach dem Controller prüft, da häufig mehrere Actions zu einem Menüpunkt gehören und man dann einen Menüpunkt mit einem Controller abdeckt.

Wie macht ihr das?

Wie ist eure Methode um diese kleine Problematik zu lösen? Habt ihr vielleicht einen schöneren/einfacheren Ansatz? Dann würde ich mich sehr freuen wenn ihr mich belehren würdet :)

8Aug/120

iOS6 Smart App Banner auf eurer Seite nutzen

Bilder von iphoneblog.de

Sicherlich kennt ihr diese hässlichen Popups auf größeren Seiten wie Welt.de die auch eine (Bezahl-)App im Appstore haben. Diese Popups sind nicht nur unschön, sondern nerven auch extrem!

In iOS6 will Apple das Ganze nun etwas verschönern und bietet den Webseiten an ein Banner über dem Seiteninhalt anzuzeigen, das die gewünschte App inklusive ein paar Informationen wie Bewertung und Hersteller enthält.

Wie das aussehen kann seht ihr in dem oberen Screenshot des Safari unter iOS6. Statt einem Popup zeigt ted.com den neuen Banner an.

Implementierung

Wenn ihr eure Seite auch mit einer App verknüpfen wollt könnt ihr das ziemlich einfach gestalten:


<meta name="apple-itunes-app" content="app-id=%APPID%, app-argument=%APPPARAMETER%">

Ihr bindet einfach den oberen Meta-Tag in eurem Header ein und der mobile Safari erledigt den Rest. Ihr habt hier dabei zwei Parameter zu befüllen, wobei der zweite optional ist.

Die App-ID ist die Id der App im Appstore. Diese findet ihr in der URL der App im iTunes Store:

http://itunes.apple.com/de/app/doodle-jump-achtung-hochste/id307727765?mt=8

Dabei gebt ihr nur die Zahl an (ohne "id").

Der zweite Parameter wird der App (falls die verlinkte App bereits installiert ist) übergeben. So könnt ihr den Besucher nahtlos in die App wechseln lassen und automatisch an die Stelle in der App springen auf der der Besucher auf der Webseite war.

Da iOS6 sich wenn es bald raus ist ziemlich schnell verbreiten wird lohnt es sich sicher schon mal die Header anzupassen ;-)

7Aug/120

Log4Net in einem ASP.NET MVC Projekt nutzen

Nutzt ihr eigentlich Logging Systeme? Ja? Wirklich? Jaja, das hätte ich jetzt auch gesagt ;-) Wenn ihr noch kein Logging in euren Web Projekten habt solltet ihr das schleunigst nachholen, denn es ist oft einfachste und schnellste Weg genaue Informationen darüber zu erhalten was in der Applikation los war als es zu einem Fehler oder Absturz kam.

Eine der einfachsten und schnellsten Möglichkeiten Logging zu implementieren ist es die fertige und sehr mächtige Library Log4Net zu nutzen. Java Entwickler werden diese als Log4J kennen und schätzen.

Am schnellsten geht es wenn ihr Log4Net über NuGet installiert:

Nun habt ihr schon mal die Assembly in eurem Projekt. Als nächstes müssen wir Log4Net konfigurieren. Das kann man zum Beispiel in der web.config machen:


    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    </configSections>

    <log4net>
        <root>
            <level value="ALL" />
            <appender-ref ref="RollingFile" />
        </root>
        <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
            <file value="app.log" />
            <appendToFile value="true" />
            <maximumFileSize value="1000KB" />
            <maxSizeRollBackups value="2" />
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %-5p %c - %message%newline" />
            </layout>
        </appender>
    </log4net>

Interessant ist hier eigentlich der Appender-Teil, denn hier definiert ihr wie geloggt werden soll. In diesem Beispiel werden alle Ausgaben in eine Datei namens app.log geloggt, weiterhin werden Informationen wie Datum, Zeit, Thread, Log-Level, Klasse und Lognachricht angezeigt. Hier gibt es unendlich viele Kombinationen.

Auf der Homepage von Log4Net findet ihr noch viele andere Beispiele für Appender-Configs, mit denen ihr direkt in eine Datenbank loggen könnt, oder die Nachrichten an einen SMTP Server senden könnt, die dann per Mail versendet werden. Natürlich kann auch auf die Konsole geloggt werden, sucht euch einfach die Appender aus die ihr benötigt und tragt diese ein, ihr könnt auch mehrere Appender kombinieren.

Bevor ihr nun losloggen könnt müsst ihr den Logger noch laden. Das macht ihr in der Application_Start-Methode in der Global.asax.cs. Hierzu reicht eine einfach Zeile:


log4net.Config.XmlConfigurator.Configure();

Wenn ihr die Konfiguration von Log4Net in eine Extra Datei auslagern wollt, könnt ihr hier auch den Pfad zu dieser Konfiguration angeben.


log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(filename));

Nun wechseln wir mal in einen Controller und loggen mal etwas:


    public ActionResult Index()
    {
        ILog logger = LogManager.GetLogger(typeof(HomeController));

        logger.Info("Index Action wurde aufgerufen.....");

        try
        {
            logger.Debug("Don't mess with math dude...");
            int zero = 0;
            int endOfWorld = 12 / zero;
        }
        catch (Exception ex)
        {
            logger.Error("Ohh noez, you're dead now!", ex);
        }

        return View();
    }

Wie man sieht funktioniert das Ganze ziemlich einfach und effektiv. Der Logger lässt euch zwischen verschiedenen Log-Leveln auswählen. In der XML-Konfiguration definiert ihr den Loglevel, dann werden nur bestimmte Dinge geloggt. So könnt ihr für Diagnosezwecke den DEBUG-Level setzen um alle wichtigen Infos zu erhalten, und später wenn alles erledigt ist den Level wieder auf INFO senken.

So sieht übrigens die Ausgabe zu dem oberen Code aus:

Im Grunde ziemlich simpel, aber sehr effektiv. Alternativ kann man auch ELMAH verwenden.

Ein Demo-Projekt findet ihr hier.

6Aug/120

Entity Framework Code First und Datenbank Migration

Das Entity Framework Code First ist ein feine Sache wenn man keine Lust auf SQL hat und diese lästigen CRUD Funktionen für die Datenbank jemand anders machen lassen will.

Besonders zu Beginn eines Projekts ist es super bequem den DropCreateDatabaseAlways-Initialisierer zu benutzen, der einem bei jeder Modeländerung eine frische und an das neue Model aktuelle Datenbank generiert. Doch irgendwann läuft die Applikation und man hat diverse Testdaten gespeichert die man nicht verlieren will, oder die App wurde nun schon installiert und ein Update steht bevor - was nun?

Natürlich kann man die Datenbank nicht mehr einfach neu erstellen mit DropCreateDatabaseAlways da dann auch alle Daten verloren gehen. Man muss die Datenbank aktualisieren, und genau hier kommen die Entity Framework Migrations ins Spiel, die seit der Version 4.3 Bestandteil des EF sind.

Falls ihr noch eine alte Version von EF verwendet solltet ihr NuGet anschmeißen und die neue Version installieren:

Ich würde euch empfehlen nun den CreateDatabaseIfNotExists-Initialisierer für eure Datenbank zu nutzen, um eure Daten nach der Modeländerung nicht zu verlieren.

Wenn ihr nun euer model ändert und versucht die App zu starten solltet ihr diesen Fehler zu sehen bekommen:

”The model backing the 'YourDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).” 

1. Nun müssen wir aktiv werden und die Datenbank-Migration aktivieren

Dazu führen wir den Befehl "Enable-Migrations" auf der NuGet Konsole aus. Dieses Kommando legt einen neuen Ordner namens "Migrations" in eurem Projekt an.

In diesem Ordner werdet ihr eine "Configurations"-Klasse finden, die ca so aussehen sollte:


internal sealed class Configuration : DbMigrationsConfiguration
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(DB context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //
    }
}

Dies sollte euch an eure Initialisierungs Klasse erinnern, denn hier habt ihr auch eine Seed-Methode, die nach der Migration ausgeführt wird und euch die Möglichkeit gibt direkt Daten in die Datenbank zu schreiben.

Ich würde weiterhin empfehlen den Konstruktor der Klasse um folgende Anweisung zu erweitern:


AutomaticMigrationDataLossAllowed = false;

Dies sorgt dafür, dass ihr keine Daten verliert wenn die Datenbank aktualisiert wird.

2. Erste Migration anlegen

Nun wind wir soweit, dass wir unsere erste Migration anlegen können, dies geschieht ebenfalls über die NuGet Konsole mit dem Befehl: "Add-Migration" Anschließend werdet ihr noch nach einem Namen für die Migration gefragt, hier könnt ihr eure Fantasie benutzen ;)

Es wird nun eine weitere Klasse in eurem Migrations-Ordner angelegt, diese hat ein Timestamp und eure Bezeichnung im Namen. Die Klasse ist in eine Up- & Down-Methode aufgeteilt, in der jeweils die Aktionen gespeichert sind, die nötig sind um die gewünschten Änderungen an der Datenbank durchzuführen oder diese Änderungen wieder rückgängig zu machen.


public partial class Initial : DbMigration
{
    public override void Up()
    {
    }

    public override void Down()
    {
    }
}

3. Migration durchführen

Nun können wir damit beginnen die Datenbank zu verändern. Hier haben wir nun zwei Möglichkeiten.

1. Direktes Update durchführen über die NuGet Konsole
2. Ein SQL Skript erzeugen und dieses dann auf dem SQl-Server ausführen

Da ich auf meinem Entwicklungsrechner keine Verbindung zu der Produktivumgebung habe, erzeuge ich eigentlich immer SQL Skripte, die ich dann auf der Remote-Maschine benutze um die Datenbank zu aktualisieren.

1. Direkt Update

Dazu nutzen wir den Befehl "Update-Database".  Dadurch wird die Datenbank auf die neueste Version aktualisiert. Wenn ihr auf einen Spezifischen Stand updaten oder downgraden wollt könnt ihr den Stand über den Parameter "-TargetMigration=$" machen. "Update-Database -TargetMigration=XXX".

Falls ihr einen älteren Stand angebt, werden die Down-Methoden der aktuelleren Migrationsklassen aufgerufen.

2. SQL Skript erzeugen

Wenn ihr dem "Update-Database" Befehl den "-Script" Parameter übergebt, wird für euch ein Migrations Skript angelegt, dass alle nötigen Änderungen enthält. Diese betreffen auch die Downgrades, falls ihr einen älderen Stand als Ziel angebt.

Dieses SQL Skript kann dann problemlos auf dem SQL Server eingespielt werden und verhält sich genau wie eine "Direkte" Migration.

Zusammenfassung

Die Entity Framework Datenbank Migration ist eine sehr bequeme Art die Datenbank auf seinem Testsystem und auch auf dem Zielsystem zu aktualisieren. Vor Allem ist es cool, dass ich jederzeit auch Zwischenreleases wiederherstellen kann.

5Apr/122

ASP.NET MVC Security Teil 2: Unnoetige HTTP Response-Header entfernen

In dieser Reihe von Posts möchte ich Wege zum Absichern einer MVC Anwendung zeigen, die man gerne mal vergisst oder als Neueinsteiger nicht gleich auf dem Schirm hat.

Teil 2: Unnötige HTTP Response-Header entfernen

Wenn wir im Internet surfen werden oft Informationen über uns ohne unser Zutun bei jedem Request an den Server übertragen. Dies geschieht über die HTTP-Header. So wird z.B. die Adresse der Seite auf der wir einen Link geklickt haben in dem Referrer-Header an den Server übertragen.

Aber auch die Server selbst sind in dieser Sache oft sehr gesprächig und verraten mehr über sich als wirklich nötig ist.

Eine Typische ASP.NET Serverantwort

In dem Bild sieht man (rot eingerahmt) Informationen die der Server über unsere Anwendung nach außen gibt, die eigentlich lieber geheim bleiben sollten.

Warum ist das gefährlich?

Die Informationen, die hier angezeigt werden verraten die Version des Servers, der Laufzeitumgebung und die Version des Frameworks, das wir benutzen. In diesem Fall ASP.NET MVC 3.

Falls nun bekannt wird, dass der Server oder ASP.NET in dieser Version eine Sicherheitslücke aufweist, sieht ein potentieller Angreifer sofort, dass unsere Seite für eine Attacke anfällig ist.

Es gibt sogar extra Tools, die das Web nach Webseiten durchsuchen, die eine Serverversion aufweisen, die als unsicher eingestuft wird oder für die es bekannte Lücken gibt. Diese Tools nutzen unter Anderem dann auch diese Informationen um zu prüfen ob es sich lohnt bei dieser Seite einen Angriff zu starten.

Was nun?

Im Grunde ist die Aufgabe sehr einfach, wir müssen diese unnötigen Serverheader ausblenden. Wenn die Webseite dann keine anderen Frameworkspezifischen Merkmale aufweist (wie z.B. einen Viewstate) ist es für einen Besucher praktisch unmöglich herauszufinden, welcher Server und welches Framework im Backend laufen.

Die Umsetzung

Leider ist ASP.NET in dieser Hinsicht noch nicht so richtig benutzerfreundlich, denn um all diese Header zu entfernen müssen wir an einigen verschiedenen Stellen Änderungen vornehmen. Gehen wir mal Schritt für Schritt alles durch.

1. ASP.NET &  MVC Header

Diesen Header können wir recht einfach entfernen, indem wir in der global.asax die nötige Property setzen:


protected void Application_Start()
{
    MvcHandler.DisableMvcResponseHeader = true; //<- Hier

    AreaRegistration.RegisterAllAreas();

    Database.SetInitializer(new F1DBInitializer());

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

Dies hat schon eine Gute Wirkung auf unsere Response Header:

Verbliebene Response Header

Die Version von ASP.NET und des MVC Frameworks wird nun nicht mehr angezeigt. Nun zu den anderen.

2. X-Powered-By Header

Um diesen Header zu entfernen müssen wir unsere web.config ergänzen (Quelle):


<?xml version="1.0"?>
<configuration>

  <system.web>
    <httpRuntime enableVersionHeader="false" />
    ...
  </system.web>

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

 ...
</configuration>

Dann verabschiedet sich auch dieser Header.

Und auch X-Powered-By ist nun weg

3. Einer geht noch: Der Server-Header

Dies geht leider nicht so einfach durch das Setzen eines Configparameters, hier müssen wir selbst Hand anlegen und diesen Header aus der Response löschen. Dazu schreiben wir uns ein eigenes HttpModul (Quelle):


public class RemoveServerHeaderModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreSendRequestHeaders += OnPreSendRequestHeaders;
    }

    public void Dispose()
    { }

    void OnPreSendRequestHeaders(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Headers.Remove("Server");
    }
}

Anschließend müssen wir das neue Modul über die web.config registrieren (Quelle):


<?xml version="1.0"?>
<configuration>
  ...
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="RemoveServerHeaderModule" type="SecurityTipp.RemoveServerHeaderModule"/>
    </modules>
	...
  </system.webServer>

</configuration>

Das Ergebnis:

Alle unnötigen Header sind raus

Nun haben wir unser Ziel erreicht und alle Plaudertaschen aus der Response entfernt :)

Weitergedacht

Hier könnte man nun ansetzen und sogar versuchen den potentiellen Angreifer in die Irre zu führen, indem man einen modifizierten Server-Header zurückgibt der auf eine Ganz andere Serversoftware verweist, Apache oder sowas ;)

Das Schöne hierbei ist weiterhin, dass wir alle diese Änderungen innerhalb unserer App machen können und nicht im IIS rumfummeln müssen. Einerseits weil man da viel kaputtkonfigurieren kann, andererseits weil man nicht immer Zugriff auf den IIS hat, wenn man z.B. nur ein Webspace hat.

Diese Schritte sollten bei jeder Anwendung durchgeführt werden, egal ob MVC, ASP.NET oder PHP, gebt den Besuchern nicht mehr Informationen als sie unbedingt benötigen!

kick it on dotnet-kicks.de

4Apr/120

ASP.NET MVC Security Teil 1: Das AntiForgeryToken nutzen

In dieser Reihe von Posts möchte ich Wege zum Absichern einer MVC Anwendung zeigen, die man gerne mal vergisst oder als Neueinsteiger nicht gleich auf dem Schirm hat.

Teil 1: Nutzen des AntiForgeryToken bei POST Requests

POST Requests sind gefährlich, da diese im Normalfall dafür verwendet werden dem Server Informationen mitzuteilen. Die Informationen sollte man natürlich prüfen, auf Form und Inhalt, aber noch wichtiger ist es, zu wissen wer uns diese Daten sendet. (Cross-Site-Attacken verhindern)

Wie funktioniert das?

Mit dem AntiForgeryToken können wir an dieser Stelle sichergehen, dass nur Formulare am Server angenommen werden, die der Server selbst erzeugt hat.
Dabei erzeugt der Server beim Generieren des Formulars einen Token und speichert diesen in einem versteckten Input-Feld (__RequestVerificationToken), des Weiteren wird auch ein Cookie namens "__RequestVerificationToken" mit dem gleichen Token angelegt, sodass beim Absenden des Formulars sowohl der Cookie als auch das versteckte Feld wieder zurück an den Server übertragen wird.

Wenn der Server diesen Request empfängt prüft er diesen Token aus dem versteckten Feld gegen das Token aus dem Cookie. Gibt es hier keine Übereinstimmung wird der Request abgewiesen.

Wie wird das implementiert?

Als Erstes muss das Token in das Formular gesetzt werden und das Cookie erzeugt werden. Diese Aufgabe übernimmt für und der kleine Html-Helper aus MVC.


<div class="myForm">
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <!-- REST DES FORMULARS -->
    }
</div>

Das ging ja einfach, nun müssen wir dafür sorgen, dass dieses Token beim Verarbeiten des Requests auch geprüft wird.


[ValidateAntiForgeryToken]
public ActionResult UpdateStuff()
{
...
}

Mehr ist das nicht, ein einfaches Attribut genügt, und unsere MVC Anwendung ist mit nur zwei Zeilen sicherer geworden.

Wenn Ihr nun einen Blick in euer gerendertes Formular werft, werdet ihr etwas in der Art finden:


<input name="__RequestVerificationToken" type="hidden" value="4PhvBw7EO5I3O4zw2cdYkaEfSJycy1Ugi8AOT6glW6IqZNnVKXTzL52LgQGNMviOhYTxAOQH3iZRtehUoHKRprcHXa8YNel6RzVmKjGAEi0W0duRpnwJu9EpR7ybAoZX9yqeiP3Pyng/ma1t/k6QhM2bbcoBgkou5y0KXEj8Ut8=" />

Gibt es Einschränkungen?

  • Da hier ein Cookie gesetzt wird müssen natürlich Cookies aktiviert sein da der Server sonst alle Requests abweisen wird.
  • Das Ganze funktioniert nur mit POST Requests, was auch logisch ist, da GET Requests nur zum Abfragen von Informationen genutzt werden sollten.

Alternativen?

Wenn man keine Cookies nutzen will kann man ein ähnliches Verhalten hervorrufen, indem man prüft ob der eingehende Request ein Referrer-Header besitzt der auf unsere eigene Domain + URL verweist.
Dies ist natürlich nicht wirklich Sicher, da es leicht zu fälschen ist und außerdem haben manche Browser Anonymisierungsfunktionen die diese Header-Felder nicht mitsenden, also ist hier Vorsicht geboten.

Zusammenfassung

Das AntiForgeryToken bietet einen recht guten Schutz vor Cross-Site-Attacken bei sehr sehr einfacher und schneller Implementierung.

kick it on dotnet-kicks.de

15Mrz/120

Chart helper in ASP.NET MVC nutzen

Vor einer Weile habe ich ein kleines Tutorial geschrieben wie ihr das kostenlose MSChart Control benutzen könnt um euch hübsche Grafen zeichnen zu lassen.

ASP.NET MVC 3 bietet euch einen Helper der eine sehr ähnliche Funktionalität bietet und sehr einfach in eure MVC Anwendung zu integrieren ist.

Das Schöne ist, dass wenn ihr das aktuelle Visual Studio Tools update installiert habt, ihr diesen Helper bereits out of the box nutzen. Falls nicht könnt ihr es über das NuGet Paket bequem nachinstallieren.

Hier ein kleines Beispiel wie eine Action aussehen kann, die ein Chart erzeugen soll:

Beispiel 1


    public ActionResult CreateChart()
    {
        Chart bytes = new Chart(width: 400, height: 200)
            .AddSeries(
                chartType: "column",
                xValue: new[] { "Wert1", "Wert2", "Wert3", "Wert4" },
                yValues: new[] { "12", "3", "23", "11" })
            .AddSeries(
                chartType: "column",
                xValue: new[] { "Wert1", "Wert2", "Wert3", "Wert4" },
                yValues: new[] { "13", "32", "23", "5" });

            return File(bytes.GetBytes("png"), "image/png");
    }

Wie man sieht wird hier nachdem das Chart erstellt wurde eine Grafik daraus gemacht und diese dann an die View zur Anzeige gesendet. Der Aufruf in der View ist dementsprechend simpel:


<img src="@Url.Action("CreateChart")" alt="Beschreibung" />

Was vielleicht nicht auf den ersten Blick ersichtlich ist, ist wie man eine legende zu dem Chart anzeigen lassen kann. Dazu muss jede "Serie" einen namen erhalten und zum Schluss kann man dann die "AddLegend()" Methode ohne Parameter aufrufen:

Beispiel 2


    public ActionResult CreateChart()
    {
        Chart chart = new Chart(width: 400, height: 200)
            .AddSeries(
                chartType: "column",
                xValue: new[] { "Wert1", "Wert2", "Wert3", "Wert4" },
                name: "Serie 1",
                yValues: new[] { "12", "3", "23", "11" })
            .AddSeries(
                chartType: "column",
                xValue: new[] { "Wert1", "Wert2", "Wert3", "Wert4" },
                name: "Serie 2",
                yValues: new[] { "13", "32", "23", "5" });

        chart.AddLegend();

        return File(chart.GetBytes("png"), "image/png");
    }

Noch etwas umständlicher wird es, wenn man nun die legende an eine andere Stelle setzen will, denn hier muss ein eigenes Theme her. Dieses sollte dann auch nur die Felder enthalten die man ändern will. Wenn man z.B. die legende unten angezeigt haben möchte kann man so vorgehen:

Beispiel 3


        public ActionResult CreateChart()
        {
            string theme = @"<Chart BackColor=""WhiteSmoke"" >
                                    <ChartAreas>
                                        <ChartArea Name=""Default"" BackColor=""White"">
                                    </ChartAreas>
                                    <Legends>
                                        <Legend _Template_=""All"" BackColor=""Transparent"" Font=""Trebuchet MS, 9pt"" IsTextAutoFit=""False"" Docking=""Bottom"" /> 
                                    </Legends>
                                </Chart>";

            Chart chart = new Chart(width: 400, height: 200, theme: theme)
                .AddSeries(
                    chartType: "column",
                    xValue: new[] { "Wert1", "Wert2", "Wert3", "Wert4" },
                    name: "Serie 1",
                    yValues: new[] { "12", "3", "23", "11" })
                .AddSeries(
                    chartType: "column",
                    xValue: new[] { "Wert1", "Wert2", "Wert3", "Wert4" },
                    name: "Serie 2",
                    yValues: new[] { "13", "32", "23", "5" });

            chart.AddLegend();

            return File(chart.GetBytes("png"), "image/png");
        }

Man beachte hier dass dem Chart-Konstruktor ein weiterer Parameter "theme" übergeben wird.

Im Grunde wars das auch schon. An der Handhabung ändert sich nicht viel. Falls ihr euch irgendwo vertippt wird übrigens einfach kein Bild erzeugt, also vorsicht beim Tippen ;)

20Feb/122

ASP.NET: Verbindungsname LocalSqlServer wurde in der Anwendungskonfiguration nicht gefunden

Am Wochenende hatte ich einen interessanten Fehler in meiner ASP.NET MVC Anwendung. Dieser tauchte auf nachdem die Anwendung schon einige Wochen Problemlos lief. Es handelte sich um diesen Fehler:

Konfigurationsfehler

Beschreibung: Fehler beim Verarbeiten einer Konfigurationsdatei, die für diese Anforderung erforderlich ist. Überprüfen Sie die unten angegebenen Fehlerinformationen, und ändern Sie die Konfigurationsdatei entsprechend.

Parserfehlermeldung: Der Verbindungsname LocalSqlServer wurde in der Anwendungskonfiguration nicht gefunden, oder die Verbindungszeichenfolge war leer.

Das Problem ist hier, dass das ASP.NET Membership per Default in der root web.config so konfiguriert ist, dass es den Connectionstring "LocalSqlServer" nutzen soll. Dieser Connectionstring zeigt dann (meistens) auf eine SQL Datenbank die auf dem Hostingsystem (noch) nicht verfügbar ist. An dieser Stelle knallt es dann.

Die einfachste Lösung für dieses Problem ist es den Connectionstring neu zusetzen. Dazu entfernt man erst den Defaulteintrag und setzt den neuen dann auf eine gültige Datenbankverbindung:


	<remove name="LocalSqlServer" />
	<add name="LocalSqlServer"
		connectionString="[EUER CONNECTIONSTRING]"
		providerName="System.Data.SqlClient" />

Dies hat das Problem behoben, sodass die Anwendung wieder wie gewohnt lief.

Was mir noch ein wenig Kopfschmerzen bereitet, ist dass ich das ASP.NET Membership gar nicht nutze und auch keinen "LocalSqlServer" Connectionstring habe. Des Weiteren lief die Anwendung erst wochenlang und plötzlich kam dann dieser Fehler.

Wenn ihr diesen Fehler vielleicht schon kennt oder euch noch was dazu einfällt würde ich mich über einen Kommentar mit einem Tipp freuen.

Get Adobe Flash player