Sie sind hier: Weblog

Benutzerdefinierte HTTP Authentifizierung mit ASP.NET MVC

Foto ,
29.09.2011 15:07:00

Natürlich, IIS selbst implementiert auch HTTP Authentifizierung. Das Problem dabei ist, dass IIS standardmäßig nur auf Windows-Benuzter/ AD-Benutzer losgeht. Möchte man dies umgehen, muss man ein benutzerdefiniertes IIS-Modul schreiben. Das ist aber nicht unbedingt wünschenswert. Zum Glück kann uns das bei ASP.NET MVC erspart bleiben. Hier bietet sich nämlich die Implementierung eines Authentifizierungsfilters an. Nachfolgend platziere ich eine Beispiel-Implementierung dazu.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;

namespace FlugBuchungsService.CustomAuth
{
    public class CustomHttpBasicAuthFilter: FilterAttribute, IAuthorizationFilter    {

        public void OnAuthorization(AuthorizationContext filterContext)
        {
            var context = filterContext.RequestContext.HttpContext;
            var request = context.Request;
            var response = context.Response;

            var header = request.Headers["Authorization"];

            if (string.IsNullOrEmpty(header) || !header.Trim().ToLower().StartsWith("basic"))
            {
                response.Headers["WWW-Authenticate"] = "Basic realm=\"flugservicedemo\"";
                filterContext.Result = new HttpStatusCodeResult(401, "Unauthorized");
                return;
            }

            header = header.Trim();
            header = header.Substring(5); // Basic wegschneiden ...
            header = header.Trim();
            header = Encoding.UTF8.GetString(Convert.FromBase64String(header));

            var index = header.IndexOf(:);
            if (index == -1)
            {
                response.Headers["WWW-Authenticate"] = "Basic realm=\"flugservicedemo\"";
                filterContext.Result = new HttpStatusCodeResult(401, "Unauthorized");
                return;

            }

            var user = header.Substring(0, index);
            var password = header.Substring(index + 1);

            if (user != "test" && password != "test")
            {
                response.Headers["WWW-Authenticate"] = "Basic realm=\"flugservicedemo\"";
                filterContext.Result = new HttpStatusCodeResult(403, "Forbidden");
            }

        }

        private static string RemovePrefix(string str, string prefix)
        {
            if (str.StartsWith(prefix))
            {
                str = str.Substring(prefix.Length, str.Length - prefix.Length);
            }
            return str;
        }
    }
}
Aktivieren kann man diesen Filter, indem man damit einzelne Action-Methoden annotiert registriert.
[CustomHttpBasicAuthFilter]
[UrlMapping("/fluege")]
public ActionResult Index()
{
    var rep = new Repository();

    var fluege = rep.FindFluege();

    return Json(fluege, JsonRequestBehavior.AllowGet);
}
Alternativ dazu kann man den Filter auch als globalen Filter registrieren.
// global.asax
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new CustomHttpBasicAuthFilter());
}