Easy Implementation of GDPR with Aspect Oriented Programming – InfoQ.com

Key Takeaways

GDPR should be a default feature, added in every single application that handles user data, especially PII (Personally Identifiable Information).

Most organizations consider GDPR as luxury and have an impression that it needs special tools and experts to implement it.

Of course, knowledge of the entire GDPR specification is required, but once we are through the rules, we can see that the frameworks and design patterns we already use in our everyday development can very well be used to implement the GDPR rules.

Going forward, all applications should be GDPR compliant.

When we talk about GDPR, the three important things we want to implement are:

Even though these are three different features, the implementation can be simplified and concentrated by using simple programming patterns.

Good news. We dont need any third-party libraries for this implementation.

[Click on the image to view full-size]

Let us assume a simple use case:

Note: We are not going to have a working database connection for this example, we will just assume that the service saves the data and returns the same to the user.

The second step is the custom annotation. Let us use standard Java to create it.

Let us break down this custom annotation:

Now this interface can be used as @GDPR in any desired method.

Spring Boot natively supports AOP. Using which, we will intercept any method that is annotated with the @GDPR annotation.

Let us go ahead and create an interceptor class.

Let us add a new method to our controller with the @GDPR annotation. The modified controller should look like below:

Let us break down this controller:The Controller/Web API has two methods with corresponding endpoints, /plain and /encrypt.

This way, the GDPR implementation does not disturb the existing business logic.

If you run the application as such and call the /plain API, you should see log statements only from the UserController and UserService classes. But when you call the /encrypt API, you should see an additional log statement from the GDPRInterceptor class. It should be noted that the log statement from GDPRInterceptor is printed first, because the controller is tapped before it calls the service, which is very critical in this implementation.

Lets create an EncryptionService class. We are not going to implement an actual working encryption for now, instead, let us consider a simple mockup of an encryption.

We have two methods:

For Example, if the data is "MySampleData," the encrypt method will return "MySampleData { ENCRYPTED }," and if you pass this output to the decrypt method, you will get back the original data.

The encrypt and decrypt methods we created are good for processing primitives. But a typical application would only deal with Java objects. It would be tedious to create individual transformers for every class type that an application deals with. For that purpose, we are going to extend the ObjectMapper class provided by Jackson Library. We are going to alter the default object serialization method to include our encryption process.First, we need to create two Custom Serializers, one for encryption and one for decryption.

The custom serializers extend JSONSerializer and override the serialize method. We are also casting this function with the Map class, which will be explained later in this article.

Let us build the custom object mappers that use these new serializers, thanks to Spring Boot configuration.

Here we have three types of ObjectMappers:

@Primary the default ObjectMapper used by Spring.@Bean("encryptor") ObjectMapper, that will encrypt the Java Object (JSON).@Bean("decryptor") ObjectMapper, that will decrypt the Java Object (JSON).

A typical application will have many types of Java classes/entities. Since we are going to reconfigure the Jackson serializer provided by Spring itself, we will not be able to include a Generic to our Serializer. It will also be tiresome to create a serializer for every class type. So we are going to generalize all Java class types as a Key Value object i.e., java.util.Map. This generalization will help us serialize and deserialize any object, without worrying about actual data type.

Consider the following scenario:

To satisfy the above scenario, we need the data to be encrypted from the controller to the service and decrypted from the service to the controller.

Let us add this transformation code to our interceptor.

The updated GDPRInterceptor has the following changes:

Call

Response

Log Statements

Call

Response

Log Statements

As you can see, the API response is the same (original data) for both APIs. However, for the encrypt API, the log statements from controller and service show encrypted data.

Both controller methods are doing the same task, but just the @GDPR implementation is doing the magic for us.

Masking sensitive data is an important aspect of GDPR compliance. Fortunately, its easy to include it in our current pattern.

Let us re-assume the scenario we discussed above.

The encryption stays the same, but when the API responds back to the user, the original data is masked. So, to satisfy this condition, we need to introduce a new method in EncryptionService for Masking and modify the decrypt method to call this new masking function.

Now if you call the /encrypt API, the response will be:

We already added logging to the interceptor. Any method that is annotated with @GDPR are sensitive methods. Whenever these methods are called, the interceptor will log it around the execution.

Note - It is recommended not to log the actual data. Log files containing PII data are considered as a security risk.

Read this article:
Easy Implementation of GDPR with Aspect Oriented Programming - InfoQ.com

Related Posts

Comments are closed.