Something like an operation filter in WCF REST?

2019-04-14 12:11发布

问题:

I am looking for something like the AuthorizeAttribute in MVC, something I can use like this:

    [WebGet(UriTemplate = "data/{spageNumber}")]
    [WebCache(CacheProfileName = "SampleProfile")]
    [WcfAuthorize]
    public IEnumerable<SampleItem> GetCollection(String spageNumber)
    {
        Int32 itemsPerPage = 10;
        Int32 pageNumber = Int32.Parse(spageNumber);
        return Enumerable.Range(pageNumber * itemsPerPage, itemsPerPage)
                         .Select(i => SampleItem.Create(i));
    }

That WcfAuthorizeAttribute, will try to authenticate the user with FormsAuthentication, and set the context's IPrincipal, or return a HTTP 401 Unauthorized.

I have tried with a IOperationBehavior, but I gets executed in the first method, whichever it be, not in the method I have set the attribute.

How can this be achieved in WCF REST?

Regards.

PS: I have seen the RequestInterceptor example in the Starter Kit, but what I want is put it in some methods only, and the example looks like a filter you execute in all the operations.

回答1:

You can use AOP to achieve this. I have used PostSharp as an AOP tool to achieve this functionality. You can also find a sample on their website. The OnMethodEntry gets executed before a method (that is decorated with this attribute) is executed and you can perform your validation there.

I did a quick sample to test this and it worked.

[Serializable]
[ProvideAspectRole(StandardRoles.Security)]
public class WcfAuthorizeAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        //extract forms authentication token here from the request and perform validation.
    }
}

And you could decorate your WCF methods like below.

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class Service1
{
    [WcfAuthorize]
    [WebGet(UriTemplate = "")]
    public List<SampleItem> GetCollection()
    {
        return new List<SampleItem>() { new SampleItem() { Id = 1, StringValue = "Hello" } };
    }