Supertext Home
Chief of the System Blog

Archive for the 'Technology' Category


Basic Authentication with WCF Web API Preview 6

Friday, February 3rd, 2012

One should not believe it, but it seems that there is no official way to use your own version of Basic HTTP Authentication with the WCF Web API in an MVC Web Application yet. So, now that I’ve used all possible necessary keywords we can dive right in.

 

We are using a custom ASP.NET Membership provider and the REST API should work with a token over Basic HTTP Authentication (like Basecamp). So, the built in Windows Basic Authentication is not an option.

After scanning dozens of posts on Stackoverflow and other resources I realized that either I have to go with the WCF REST Contrib library or with Open Rasta. But since I already started with the WCF Web API Preview 6 to build my REST API (and it worked fine so far) I didn’t want to switch now.

The most promising solution I found was from jslaybaugh. He is basically using a custom version of the [Authorize] attribute from the normal MVC framework and somehow integrated it all with Ninject. For some reason I didn’t got it working. In general AuthorizeAttribute and action filters are MVC specific. For WCF we have the HttpOperationHandler or the DelegatingHandler. They have their specific uses and advantages. Some info about his from Glenn Block.

I’ve decided to go with the HttpOperationHandler and found a good example from Phil Haack where he implements a Role authorization Module, that also works with Attributes, so we can implement something very similar to the AuthorizeAttribute of MVC. There are simpler solutions, e.g. you could just check this inside your Controller, but Craig Stuntz has some good points about why this is a bad idea.

So, let’s look at the code (which is a potpourri of all the above examples):

[AttributeUsage(AttributeTargets.Method)]
public class BasicHttpAuthorizationAttribute : Attribute
{
    bool requireSsl = true;
 
    public bool RequireSsl
    {
        get { return requireSsl; }
        set { requireSsl = value; }
    }
}

With this simple BasicHttpAuthorizationAttribute class we can achieve the the attribute functionality. So we can use it like this:

[BasicHttpAuthorization(RequireSsl = true)]
[WebGet(UriTemplate = "")]
public IEnumerable<exampleobject> Get()
{

 

The RequireSsl is just an example property, you could also do a role membership check in the same way.

But the most important part is the implementation of the HttpOperationHandler. We pass the BasicHttpAuthorizationAttribute as an argument.

There are three main points that deserve attention here:

  1. If the user is not authenticated yet or provides the wrong credentials we return a HttpResponseException in the OnHandle method. We set the status code to 401 and add the WWW-Authenticate = Basic header. This creates the functionality, where the browser asks for a username/password and then automatically resends the request.
  2. In ParseAuthHeader we get the username and password out of the request. You can  then use this info with in your own way. For example with your own custom membership provider.
  3. If the user can access this method, we create a GenericPrincipal and assign it to HttpContext.Current.User. Afterwards you can then just use your normal MemberShip and RoleProvider like in every normal ASP.NET application.

Other than that, there is not much magic in here.

public class BasicHttpAuthorizationOperationHandler : HttpOperationHandler<httprequestmessage httprequestmessage ,>
{
 
    BasicHttpAuthorizationAttribute basicHttpAuthorizationAttribute;
 
 
    public BasicHttpAuthorizationOperationHandler(BasicHttpAuthorizationAttribute authorizeAttribute)   
        : base("response")
    {
        basicHttpAuthorizationAttribute = authorizeAttribute;
    }
 
 
    protected override HttpRequestMessage OnHandle(HttpRequestMessage input)
    {
        if (Authenticate(input))
        {
            return input;
        }
        else
        {
            var challengeMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized);
            challengeMessage.Headers.Add("WWW-Authenticate", "Basic");
            throw new HttpResponseException(challengeMessage);
        }
    }
 
 
 
    private bool Authenticate(HttpRequestMessage input)
    {
        if (basicHttpAuthorizationAttribute.RequireSsl && !HttpContext.Current.Request.IsSecureConnection && !HttpContext.Current.Request.IsLocal) return false;
 
        if (!HttpContext.Current.Request.Headers.AllKeys.Contains("Authorization")) return false;
 
        string authHeader =  HttpContext.Current.Request.Headers["Authorization"];
 
        IPrincipal principal;
        if (TryGetPrincipal(authHeader, out principal))
        {
            HttpContext.Current.User = principal;
            return true;
        }
        return false;
    }
 
 
    private bool TryGetPrincipal(string authHeader, out IPrincipal principal)
    {
        var creds = ParseAuthHeader(authHeader);
        if (creds != null)
        {
            if (TryGetPrincipal(creds[0], creds[1], out principal)) return true;
        }
 
        principal = null;
        return false;
    }
 
 
    private string[] ParseAuthHeader(string authHeader)
    {
        // Check this is a Basic Auth header 
        if (authHeader == null || authHeader.Length == 0 || !authHeader.StartsWith(&quot;Basic&quot;)) return null;
 
        // Pull out the Credentials with are seperated by ':' and Base64 encoded 
        string base64Credentials = authHeader.Substring(6);
        string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(new char[] { ':' });
 
        if (credentials.Length != 2 || string.IsNullOrEmpty(credentials[0]) || string.IsNullOrEmpty(credentials[0])) return null;
 
        // Okay this is the credentials 
        return credentials;
    }
 
 
    private bool TryGetPrincipal(string userName, string password, out IPrincipal principal)
    {
        // this is the method that does the authentication 
        // you can replace this with whatever logic you'd use, but proper separation would put the
 
        if (userName.Equals("remy@test.ch") && password.Equals("test"))
        {
            // once the user is verified, assign it to an IPrincipal with the identity name and applicable roles
            // Example:
            //principal = new GenericPrincipal(new GenericIdentity(userName), System.Web.Security.Roles.GetRolesForUser(userName));
 
            principal = new GenericPrincipal(new GenericIdentity(userName), new string[] {"Admin", "User"});
 
            return true;
        }
        else
        {
            principal = null;
            return false;
        }
    }
}

Last but not least, we need to hook up our HttpOperationHandler with the BasicHttpAuthorizationAttribute object and route. For this we create a custom WebApiConfiguration and use a class extension to do the wiring. Honestly, I’m not really sure what is going on here, but it works :-)

public class ApiConfiguration : WebApiConfiguration
{
    public ApiConfiguration()
    {
        EnableTestClient = true;
 
        RequestHandlers = (c, e, od) =>
        {
            // TODO: Configure request operation handlers
        };
 
        this.AppendAuthorizationRequestHandlers();
    }
}
 
 
public static class ConfigExtensions
{
    public static void AppendAuthorizationRequestHandlers(this WebApiConfiguration config)
    {
        var requestHandlers = config.RequestHandlers;
        config.RequestHandlers = (c, e, od) =>
        {
            if (requestHandlers != null)
            {
                requestHandlers(c, e, od); // Original request handler
            }
            var authorizeAttribute = od.Attributes.OfType<basichttpauthorizationattribute>()
              .FirstOrDefault();
            if (authorizeAttribute != null)
            {
                c.Add(new BasicHttpAuthorizationOperationHandler(authorizeAttribute));
            }
        };
    }
}

And we pass this configuration in the global.asax.cs to the route handler:

public static void RegisterRoutes(RouteCollection routes)
{
    var config = new ApiConfiguration();
 
    routes.Add(new ServiceRoute("example", new HttpServiceHostFactory() { Configuration = config }, typeof(ExampleAPI)));
 
}

That is it. You can download the example project here: BasicAuthenticationWithWcfWebAPI.zip

 

Please let me know if this works for you and specially, if you find ways to improve it.


A WPF project running from the CMD Prompt or as a Service and has a GUI

Thursday, November 3rd, 2011

Very often it’s necessary to run scheduled jobs or maintenance tasks once a day, once a month or even every few minutes. This can be easily achieved by creating your own Windows Service. For example if you want to send reminder e-mails to your customers. But wouldn’t it be nice to be able to also call the application from the command line so that it can do all the work and shut down afterwards? There is even a possibility of making a small script that calls all your similar applications, checks if any work has to be done, does the work and then shuts down. Also, you would like to make it possible to check for any work that needs to be done just by clicking on one button? Well, here you can find a very simple example on how all of this can be done.

First we need a class that is derived from ServiceBase. In that class need a public constructor, an OnStart and an OnStop method. For example, we want to make a service that does some usefull work every 4 minutes. An example of the code for the ServiceBase derived class is given next.

 
public class ServiceClass : ServiceBase
{
    protected System.Timers.Timer timer = new System.Timers.Timer(300000));
 
    /// <summary>
    /// Public constructor that initializes the service and
    /// sets its parameters like ServiceName.
    /// </summary>
    public ServiceClass()
    {
        CanPauseAndContinue = true;
        CanShutdown = true;
        ServiceName = "My Service Name";
    }
 
    /// <summary>
    /// Method specifies what code to execute each time a service
    /// is started. Here it configures parameters for the timer
    /// </summary>
    /// <param name="args"></param>
    protected override void OnStart(string[] args)
    {
        timer.Enabled = true;
        timer.AutoReset = true;
        timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    }
 
    /// <summary>
    /// Method specifies what code to execute each time a service
    /// is stopped. Here it configures parameters for the timer. 
    /// </summary>
    protected override void OnStop()
    {
        timer.Enabled = false;
    }
 
    /// <summary>
    /// Method specifies what code to execute each time a timer's
    /// interval is up. Here will be all the code that has to be done
    /// continuously. 
    /// </summary>
    /// <param name="source"></param>
    /// <param name="e"></param>
    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        //do some work
    }
}

We also need a class that extends the class Installer. In that class we need to define at least the class constructor method. There we create all the installer objects necessary to install the application as a service.

 
[RunInstaller(true)]
public class MyProjectInstaller : Installer
{
    private ServiceInstaller serviceInstaller;
    private ServiceProcessInstaller processInstaller;
 
    /// <summary>
    /// The public constructor that is executed when the
    /// installation is started.
    /// </summary>
    public MyProjectInstaller()
    {
        processInstaller = new ServiceProcessInstaller();
        serviceInstaller = new ServiceInstaller();
 
        processInstaller.Account = ServiceAccount.LocalSystem;
 
        serviceInstaller.StartType = ServiceStartMode.Automatic;
        serviceInstaller.ServiceName = "My Service Name";
 
        Installers.Add(serviceInstaller);
        Installers.Add(processInstaller);
    }   
}

The code given here is the minimal code needed for the service to be installed. In the class constructor we first need to instantiate the installer objects needed for the installation. One installer is an object from the class ServiceProcessInstaller and the other one is an object of the class ServiceInstaller. Then we set up all the information about the service – how will the service start (automatically), on what account will the service run(local system) and the name of the service (My Service Name). The name has to be the same as the name defined in the ServiceBase derived class. In the end we add the two created installers to the collection of installers.
If we want some additional work done on each install or uninstall, it is possible to override the methods OnBeforeInstall and OnBeforeUninstall. For example, if we want the service to be started only if there is a certain parameter, it is possible to add this code :

 
protected override void OnBeforeInstall(System.Collections.IDictionary savedState)
{
    Context.Parameters["assemblypath"] = "\"" + 
        Context.Parameters["assemblypath"] + "\" -service";
        base.OnBeforeInstall(savedState);
}
 
protected override void OnBeforeUninstall(System.Collections.IDictionary savedState)
{
    Context.Parameters["assemblypath"] = "\"" + 
        Context.Parameters["assemblypath"]   + "\" -service";
        base.OnBeforeUninstall(savedState);
}

After doing the work required for changing the call to the service, we call the same method from the base class in order to install the service correctly.
After creating the two classes necessary for defining a windows service, we have to define the main application activity. So, what we have to do is add code that will define when the application will be executed as a windows service and when it’ll just do the work once and shutdown.

public partial class App : Application
{
   protected override void OnStartup(StartupEventArgs e)
   {
       base.OnStartup(e);
       string[] commandLineArgs = System.Environment.GetCommandLineArgs();
 
       if(commandLineArgs.Length>1 && commandLineArgs[1].Equals("-someWork"))
       {
         //do some work
       }
 
       else if(commandLineArgs.Length>1 && commandLineArgs[1].Equals("-service")) 
       {
          ServiceBase.Run(new ServiceClass());
       }
       else
       {
          // do some work
       }  
    }
}

This way it is possible to manage for the application to do different work when it’s called in different ways. All the work that the application does (as the service or called from the command line) should be defined in a separate class.
In order to install the new service, open command prompt and type:

installutil ProjectName.exe

where project name is the name of the project with the windows service and it’s installer. In order to uninstall the service type :

installutil /u ProjectName.exe

And that’s it! Your service is ready to be used! Now if we want to be able to start the application with a user interface, it’s necessary to make some changes to the class App in the method OnStartup and we also have to define the class MainWindow which will contain the entire code that needs to be done through the user interface.
In the case described above, the OnStartup class will look similar to this :

public partial class App : Application
{
   protected override void OnStartup(StartupEventArgs e)
   {
       base.OnStartup(e);
       string[] commandLineArgs = System.Environment.GetCommandLineArgs();
 
       if(commandLineArgs.Length>1 && commandLineArgs[1].Equals("-someWork"))
       {
	   //starting the application with the appropriate command arguments will start 
	   //it in console mode
           MainWindow f = new MainWindow();
           f.ConsoleMode = true;
           //do some work
        }
        else if(commandLineArgs.Length>1 && commandLineArgs[1].Equals("-service")) 
        {
	    //start application as a service
            ServiceBase.Run(new ServiceClass());
        }
        else
        {
            //in case there were no command arguments, start the user interface and do    //some work
            MainWindow f = new MainWindow();
            f.ShowDialog();
            this.Shutdown();
        }            
    }
}

In the class Application there is a property ConsoleMode which is used to indicate whether or not the application mode of running is console mode. Property ConsoleMode is defined in the class that defines the user interface, MainWindow. If we are also using some of the methods defined in the class MainWindow even when we start the application from the command line, we have to find a way to indicate that the application should shut down after the work is done. That’s why in the class that describes the user interface we have to add this wherever we want to check if the application needs to be shut down:

if (ConsoleMode)
{
    Dispatcher.Invoke(new Action(() => { Application.Current.Shutdown(); }));
}

And that’s it! Now you have built your first application that can be used as a windows service, with a user interface or called from the command line.


IE9 does not color links anymore

Thursday, October 27th, 2011

 

IE9 Cache

We run a few times into the issue, that IE9 does not save the browsing history anymore. Which results in all links loosing the different color after you click on them.

There are different solutions for this on the internet, the most common being to just clear your browser cache. Which unfortunately also clears all your passwords, links and defaults for forms.

Aber better but a bit more tricky way is to delete the index.dat file in the History directory.

Just follow the steps below:

  1. Open a Command Prompt Window (cmd.exe)This does NOT work with the Windows Explorer, you need the command line.
  2. Go to C:\Users\<<UserName>>\AppData\Local\Microsoft\Windows\History(Replace <<UserName>> with your Windows account name)
  3. cd Low
  4. cd History.IE5
  5. del/a index.dat

That should be it. Let me know if it worked. It work for us.


SDL Trados Studio 2009 startup slow?

Friday, December 10th, 2010

SDL_License_Manager

Does it take minutes to load Trados? In our case, it took up to 20 minutes to load Trados. Normally Trados should start in a few seconds.

We are using a floating license with a license server in our private network. I think all this does not apply if you have a local license on your PC.

If you have the same problem, check the following things first:

  • Switch off the firewalls on both the client and the license server.
  • If VM Ware is running parallel on the server, disable it.
  • Are you using switches on the network? Could cause problems. Try a direct connection.
  • The Flex License Server should run on Port 27000, make sure it does and make sure the  client connects to it on that port. Eg. 27000@<my_server>
  • Make sure you everything is from Trados 2009 and that you don’t have any other versions running.
  • The license server has to run on a fixed IP. This is core!

Got the hints from Grzegorz Gryc.

Now, in our case the problem was a bit complicated. Our license server was not running on a fixed IP, for some reason the DHCP server is handing out the IP addresses in some weird way (normally every PC gets the same address every time it connects). Anyway, we fixed that, but still it took ages for Trades to start up. At least we didn’t get the License Server Dialog anymore.

The 2nd problem was, that Trados was scanning all possible IP addresses that the license server ever had (even though now it was fixed).

To solve this do the following:

  1. Start the SDL License Manager (under the SDL Program group)
  2. Click on “License Locations”
  3. Remove all locations and make sure there is just one with the right fixed IP of the license server

That’s it! I hope your Trados is starting faster now!


IIS7: Worker process reached its allowed processing time limit

Wednesday, August 4th, 2010

You just lost your ASP.NET session object and your app restarted? Check the Event Log for the following message:

A worker process with process id of ’23232′ serving application pool ‘ASP.NET v4.0′ has requested a recycle because the worker process reached its allowed processing time limit.

I’ve already posted the solution for this for IIS6. It’s basically the same for IIS 7.

Go to the Application Pools section of your IIS. Right-click on the right pool and choose Recycling.

IIS7 Application Pool recycling

Here you can adjust when you want you Application Pool to recycle. No recycling is not really recommended. So either out put in a very high number of requests or you choose fixed time when you assume there are no users on your site.

Specify a time for recycling

We decided to just recycle during the night.

What would be nice is to get some kind of notification, so one could save all ASP.NET sessions and then restore them afterwards.


Recursive file copy with wildcard on Windows

Friday, July 30th, 2010

I was looking for a way to copy only certain file types from one folder to another. Basically a recursive copy with a filter.

There are different solutions, but here I found the best one, that does not need any additional tools.

http://www.vistax64.com/powershell/30490-copy-item-recurse-wildcard.html

 

Just open the Windows Powershell and type the following command:

copy-item -rec -filter *.resx C:\source_dir  C:\target_dir

This will copy all files with the ending .resx from source_dir to target_dir.

Problem solved.

  • Topics
  • Archive
  • Subscribe
  • Facebook
  • Twitter