ASP.NET WebAPI Conditional Serialization Based on a User Role

I have an ORM (NHibernate) that maps to POCOs that will be returned to ApiControllers. I understand that JSON.NET allows me to put conditional serialization methods (ShouldSerialize *) on my models; however, these models and their methods do not know anything about their environment and should not. What I would like to do is conditionally serialize the model or one or more of its properties based on the user's role when they entered my site. I can conceptually understand how this can be done, but I was lost on the one hand. Here's a sample model:

public class SomeModel { public string SomeProperty { get; set; } [Sensitive] public string SomeOtherProperty { get; set; } } 

I would like to be able to put a property attribute so that it designates it as “Sensitive”. Then in my WebApi, when it serializes it for output, I would like it to check the model for this attribute, and if it exists, it should check the user role. If the user is in the specified role, the serializer must serialize the attribute, otherwise it either disguises it or simply does not serialize it. So do I have to write my own custom formatter to handle this, or is there a way to connect to the built-in to perform this check? Or am I too limited in my thoughts, and is there another way to handle this?

I thought that the other way this could be handled would be at the ORM level, but could not find good examples on the Internet.

Very valuable!

EDIT: here I found another similar question: Contextual serialization from a WebApi endpoint based on permissions but there was no solution. In addition, I do not like the idea of ​​installing role-based access in models through attributes. I believe this should be handled in a web application.

+7
c # serialization asp.net-web-api nhibernate sensitive-data
source share
3 answers

As already mentioned in the question, I raised the question " Contextual serialization from the WebApi endpoint based on permissions , which I answered myself. At first I looked at using MediaFormatter , but I believe that this will limit you to what answer you could return. If you want to return JSON and XML, you will need to implement two formats: To only implement the filter in one place, you need to go above the stack to the DelegatingHandler .

In my implementation, I wanted to see in which fields the client had access and delete any answer that the client should not see. This is very similar to what you want to do.

In your senario you will need to flip the object and select any fields containing your attribute and set these values ​​to null. If you return JSON or XML, then the properties are not included in the response if the values ​​are zero, so you do not even miss the name of the property.

Example

Here is an example implementation of the DelegatingHandler that uses reflection to filter the properties of a response object that implements the Sensitive attribute. It is assumed that the hierarchy of objects is flat, so if you have nested objects, you will need to navigate the graph of objects and do the same for each object in the hierarchy.

 public class ResponseDataFilterHandler : DelegatingHandler { protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken) .ContinueWith(task => { var response = task.Result; //Manipulate content here var content = response.Content as ObjectContent; if (content != null && content.Value != null) { FilterFields(content.Value); } return response; }); } private void FilterFields(object objectToFilter) { var properties = objectToFilter .GetType() .GetProperties( BindingFlags.IgnoreCase | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public); foreach (var propertyInfo in properties) { if (propertyInfo.GetCustomAttributes(typeof(SensitiveAttribute), true).Any()) { propertyInfo.SetValue(objectToFilter, null, new object[0]); } } } } 
+7
source share

The proposed solution that I came up with is for my ApiController to inherit from BaseApiController, which overrides the initialization function to set the appropriate formatter based on the user role:

 protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext) { base.Initialize(controllerContext); // If the user is in a sensitive-data access role controllerContext.Configuration.Formatters.Add(/*My Formatter*/); // Otherwise use the default ones added in global app_start that defaults to remove sensitive data } 
0
source share

You can use conditional serialization built into Json.Net. Here is an article describing it.

http://blog.mariusschulz.com/2013/04/15/conditionally-serializing-fields-and-properties-with-jsonnet

Perhaps the "ShouldSerialize ..." methods can check the current principal, from which you can check its roles?

0
source share

All Articles