Skip to content

Instantly share code, notes, and snippets.

@scottmcarthur
Created January 23, 2014 12:00
Show Gist options
  • Save scottmcarthur/8577465 to your computer and use it in GitHub Desktop.
Save scottmcarthur/8577465 to your computer and use it in GitHub Desktop.
Basic Authentication, Multiple repositories - ServiceStack v4
using System;
using System.Linq;
using ServiceStack;
using ServiceStack.Auth;
using ServiceStack.Web;
using System.Net;
using System.Text;
using System.Collections.Generic;
namespace Testv4
{
class MainClass
{
public static void Main()
{
// Very basic console host
var appHost = new AppHost(500);
appHost.Init();
appHost.Start("http://*:8082/");
Console.ReadKey();
}
}
public class MyUserRepository
{
public string Name { get; set; }
public Dictionary<string, string> Users { get; set; }
public MyUserRepository(string name, Dictionary<string, string> users = null)
{
Name = name;
Users = users ?? new Dictionary<string, string>();
}
}
public class AppHost : AppHostHttpListenerPoolBase
{
public AppHost(int poolSize) : base("Test Service", poolSize, typeof(TestApp).Assembly) {}
public override void Configure(Funq.Container container)
{
container.Register<MyUserRepository[]>(c => new[]
{
new MyUserRepository("Simpsons", new Dictionary<string, string> {
{ "cburns", "excellent" },
{ "bartsimpson", "Ay caramba" },
{ "homersimpson", "donuts" }
}),
new MyUserRepository("Superheros", new Dictionary<string, string> {
{ "thehulk", "pebbles" },
{ "captainamerica", "redwhiteblue" },
{ "spiderman", "withgreatpower" }
})
});
}
}
public class BasicAuthAttribute : RequestFilterAttribute {
readonly string _realmName;
readonly string _repositoryName;
public BasicAuthAttribute(string realmName, string repositoryName = null)
{
_realmName = realmName;
_repositoryName = repositoryName ?? realmName;
}
public override void Execute(IRequest req, IResponse res, object requestDto)
{
// Get the correct repository to authenticate against
var repositories = HostContext.TryResolve<MyUserRepository[]>();
MyUserRepository repository = null;
if(repositories != null)
repository = repositories.FirstOrDefault(r => r.Name == _repositoryName);
// Determine if request has basic authentication
var authorization = req.GetHeader(HttpHeaders.Authorization);
if(repository != null && !String.IsNullOrEmpty(authorization) && authorization.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
{
// Decode the credentials
var credentials = Encoding.UTF8.GetString(Convert.FromBase64String(authorization.Substring(6))).Split(':');
if(credentials.Length == 2)
{
// Try and match the credentials to a user
var password = repository.Users.GetValueOrDefault(credentials[0]);
if(password != null && password == credentials[1])
{
// Credentials are valid
return;
}
}
}
// User requires to authenticate
res.StatusCode = (int)HttpStatusCode.Unauthorized;
res.AddHeader(HttpHeaders.WwwAuthenticate, string.Format("basic realm=\"{0}\"", _realmName));
res.EndRequest();
}
}
public static class TestApp
{
[Route("/TheSimpsons", "GET")]
public class TheSimpsonsRequest : IReturnVoid {}
[Route("/Superheros", "GET")]
public class SuperherosRequest : IReturnVoid {}
public class TestController : Service
{
[BasicAuth("The Simpsons", "Simpsons")]
public object Get(TheSimpsonsRequest request)
{
return new { Town = "Springfield", Mayor = "Quimby" };
}
[BasicAuth("Superheros")]
public object Get(SuperherosRequest request)
{
return new { Publishers = new[] { "Marvel", "DC" } };
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment