2

I am writing a WCF service using .NET 4.5 and SimpleInjector. It is a REST service (using http/get/post).

I need to add an authorisation layer to my service. After a lot of messing around, I now have a custom authorisation manager based on ServiceAuthorizationManager.

All the examples I've seen (and I have found many) have hard coded username and password checking. I would like to use a database, and therefore want to inject the data layer into my class. If I change the constructor to take a parameter, it throws an exception "No parameterless constructor defined for this object".

This is the example I based my code off: https://msdn.microsoft.com/en-us/library/ms731774(v=vs.110).aspx I added a constructor with an interface:

public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
    public MyServiceAuthorizationManager (IMyDataLayer mdl)
    { ...

Custom "Basic" Authentication for my WCF services. REST and RIA. Possible?

Community
  • 1
  • 1
Neil
  • 11,059
  • 3
  • 31
  • 56
  • Please can you include the code that throws the error and the full stack trace? – qujck Mar 21 '16 at 15:57
  • This is the example I based my code off: https://msdn.microsoft.com/en-us/library/ms731774(v=vs.110).aspx – Neil Mar 21 '16 at 16:23
  • It's a REST service using WCF? Are you sure you want to do that? WCF kinda sucks and if you do REST, Web API makes this much easier. I think you would make your life much easier if you apply [this practice](https://cuttingedge.it/blogs/steven/pivot/entry.php?id=95) using Web API, as can be seen in [this repository](https://github.com/dotnetjunkie/solidservices). – Steven Mar 21 '16 at 16:24
  • 1
    @Steven That's exactly what I'm doing. – Neil Mar 21 '16 at 16:28

1 Answers1

4

What you probably did is configure your manager class in a behavior of your configuration file (as the MSDN article shows):

<serviceBehaviors>
  <behavior name="CalculatorServiceBehavior">
    <serviceAuthorization serviceAuthorizationManagerType="Samples.MyServiceAuthorizationManager,MyAssembly" />
  </behavior>
</serviceBehaviors>

In that case WCF is completely in control over the creation of this type; not Simple Injector. This means that it requires a default constructor.

The first solution that comes to mind is to make that class a Humble Object and let it delegate to the real authentication logic that you place into a real service. This basically means that your Humble Object does nothing more than calling into the container to resolve the real service and call its appropriate method. Resolving should be done inside the Humble Object's class and the 'real' service should not be cached.

Another option is to configure your manager from code (as MSDN also shows) by resolving it from the container and assigning it to WCF:

serviceHost.Authorization.ServiceAuthorizationManager =
    container.GetInstance<MyServiceAuthorizationManager>();

But care must be taken here, because the manager now becomes a singleton because WCF will hold on to it forever. Don't do this unless all its dependencies are singleton as well. Make sure you register your manager explicitly in the container as singleton, so the container can check for captive dependencies for you when you call Verify.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • 1
    As you suggest, I had used the configuration file version, and had eventually got to the serviceHost.Authorisation too. I was concerned about basically a singleton handling all authorisation. I will investigate the Humble object (not a pattern I have come across before. Thanks. – Neil Mar 22 '16 at 09:02
  • I have accepted your answer, because it basically confirms my suspicions and gives a suitable work around. – Neil Mar 22 '16 at 09:04