In a web service like the OData or other web API services, you might encounter into a situation to restrict some users to access some sensitive information, but not the entire data source. Usually, the best design is to lock down restricted data in the database level with some anchor tecniques. However, this might require you to change the majority of the APIs and stored proceedures signatures which is a significant amount of work and long way to test.
Alternatively, you can do a filtering against either the request or response. This article wants to elaborate the request filtering approach in a ASP.NET stack.
To begin with the solution, we need to understand the concept of
http module in ASP.NET stack. By searching the keyword, you will see a lot of good resources online. So I will focus on how to create a customized http module.
The ASP.NET stack provides you a list of event life cycle which you can register during the initialization. So the above example provides a foundation to create a customized http module. Note the
protected virtual void Dispose function, you will need to implement a proper disposible pattern in order to cover the potential memory leaks.
To enable this customized module, you can just add the configuration into your
Web.config file, then IIS will pick up from there.
By far, we have a separate HTTP module to handle the request. We will put all the filtering implementation into this module because it’s the least couple way with the original OData service, and you can easily turn on or off via the Web.config file.
The reason we choose
PostAuthenticateRequest event is because we should get the authenticated user already. So your
OnPostAuthenticateRequest callback should have some logic like the following code.
private void OnPostAuthenticateRequest(object sender, EventArgs args)
GET request, it’s straightforward to handle but
POST request needs to be handled in a different way:
request filter. Essentially, request filter is a
Stream which you can read the POST content, then write back to the pipeline. You cannot do it inside the http module, because the request InputStream is
A good starting point to understand how to intercept the
POST via request filter can be found in this MSDN article. One interesting thing you might need to pay attention is that the original stream is loaded from the stack is not at the constructor time. It is right before the first
read(). Therefore, you need to do a
TryLoadStream() for all the methods just in case they are not called in the right order.
// this code only show the critical part!
Now you can apply your filtering rules to both
POST requests. The overhead it brings to your web services is minimal as long as you keep your rule simple and straightforward.