Creating Spring Boot MVC application with AWS DynamoDB in 10 mins

Image
AWS DynamoDB DB is a serverless NOSQL database. You can understand how to build a spring boot Java web MVC application (Game Leaderboard) reading a AWS DynamoDB in 10 mins. Source of the demo code: https://github.com/babysteps-topro/spring-mvc-dynamodb Command to run the project: mvn spring-boot:run Video explain the table design: https://youtu.be/V0GtrBfY7XM Prerequisite: Install the AWS CLI: https://youtu.be/pE-Q_4YXlR0 Video explain the how to create the table: https://youtu.be/sBZIVLlmpxY

Writing your spring security expression language annotation - PART 1

Spring security expression language is very useful. It helps to secure your service/web methods with one line of code. It supports @PreAuthorize and @Secured. In the coming three posts, I will talk about how to add custom behaviour to the @PreAuthorize annotation.

Part 1 - Customize "hasPermission()" expression
Part 2 - Add new customize method security expression
Part 3 - Override default behaviour of spring security expression (e.g. hasRole() , permitAll() ...)

In this post, I will discuss how to add custom rule for permission checking in your application. This is somewhat similar to what describe in Sold Craft's post. You can reference it for more details.


Step 1: Add configuration in your spring security xml file.

You should first add the DefaultMethodSecurityExpressionHandler. It will instantiate a default MethodSecurityExpressionRoot which provides you all the default security expression (e.g. isAutghenticated(), isAnonymous() ,etc ) .

Besides, you have to add a permsisionEvaluator for that ExpressionHandler. If you are using spring security ACL, you could use AclPermissionEvaluator. In our case, we would create a BasePermissionEvaluator as our permission evaluator. You will see in step 2 that we would define custom rules in this permission evaluator.


<sec:global-method-security pre-post-annotations="enabled">
  <sec:expression-handler ref="expressionHandler"/>
</sec:global-method-security>

<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandlerr">
    <property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>  

<bean id="permissionEvaluator" class="org.borislam.security.BasePermissionEvaluator"/>



Step 2: Create your PermissionEvaluator class
You must define a class that implements the org.springframework.security.access.PermissionEvaluator. You have to override the hasPermission() method and define custom rule in this class.

In my example, the user object contains a HashMap which stored the permissions of the user. I will perform checking the permission String against this Hashmap. This HashMap is populated during login by a filter. This part will not be skipped in this example.

For similicity, I just ignore targetDomainObject parameter in my example. By using the targetDomainObject, you can further define security rules on certian domain object of your application.

public class BasePermissionEvaluator implements PermissionEvaluator{
 
 
 @Override
 public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
  boolean hasPermission = false;
  if ( authentication != null &&  permission instanceof String){

   //implement the permission checking of your application here   
   //you can just check if the input permission is within your permission list

   //In my example, the user object contains a HashMap which stored the permission of the user.
   //The HashMap<String, PrivilegeResult> is populated during using login by filter. This will not be shown in this example 

   User user = SecurityUtil.getUserCredential();
   HashMap<String, PrivilegeResult> pMap =user.getPrivilegeMap();
   PrivilegeResult privResult = pMap.get(permission); 
   hasPermission =  privResult.isAllowAccess();

  } else {
   hasPermission =false; 
  }
  return hasPermission;
 }

 @Override
 public boolean hasPermission(Authentication authentication,
   Serializable targetId, String targetType, Object permission) {
    throw new RimtimeException("Id and Class permissions are not supperted by this application");
 }
}
\
Step 3: Example usage
You could simply add your the @PreAuthorize("hasPermission()") to secure your method.

@PreAuthorize("hasPermission(#user, 'allowDoSomething')")
 public String doSomething()
 {
  //do something
  System.out.println("Do something");
 }

In the next part of this series of tutorial, I will further discuss how to add your new custom method to the security expression root.

Comments

Unknown said…
This comment has been removed by the author.
Unknown said…
This comment has been removed by the author.
Unknown said…
Excellent article, this helped me a lot.

As some additional info for other people how find this, you can also use this in your Spring MVC web UI using the <sec:authorize> tags.

The configuration is much the same, you just need to configure your own instance of DefaultWebSecurityExpressionHandler

<http authentication-manager-ref="restAuthenticationManager" pattern="/rest/**">
<intercept-url pattern="/rest/**" access="ROLE_USER" />
<http-basic />
<expression-handler ref="webExpressionHandler"/>
</http>

<beans:bean id="webExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="permissionEvaluator"/>
</beans:bean>
Anonymous said…
Good series of articles - thank you. But I have a question. You are using: hasPermission(#user, 'allowDoSomething') but you ignore the first argument. Is there a reason for this? I ask because in my hasPermission handler, targetDomainObject - that which #user refers to - is always null. Do you have to do something special to have #user map to something?
Haidar Dahnoun said…
Excellent thanks

But remove extra 'r' in
DefaultMethodSecurityExpressionHandlerr
Unknown said…
Hi,

Could you post your whole project using git or something else, as i am facing some issues related to file you have use.

One more thing could you please update your post regarding the same above for spring boot.

Popular posts from this blog

Sample Apps: Spring data MongoDB and JSF Integration tutorial (PART 1)

Customizing Spring Data JPA Repository

Adding Hibernate Entity Level Filtering feature to Spring Data JPA Repository