Home  >  Spring Security

@PreFilter and @PostFilter in Spring Security

By Arvind Rai, December 28, 2013
@PreFilter and @PostFilter is a strong feature in spring security to filter collection or arrays on the basis of authorization. This can be achieved using expression-based access control in spring security. @PreFilter filters the collection or arrays before executing method. @PostFilter filters the returned collection or arrays after executing the method. Spring security provides a built-in object named as filterObject at which @PreFilter and @PostFilter performs filtering task. @PreFilter and @PostFilter can be used on service layer with @PreAuthorize and @PostAuthorize. Use interface to declare the filter operation.
IBookService.java
package com.concretepage.service;
import java.util.List;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import com.concretepage.bean.Book;
public interface IBookService {
	@PreAuthorize ("hasRole('ROLE_READ')")
	@PostFilter ("filterObject.owner == authentication.name")
	public List<Book> getBooks();
	
	@PreFilter("filterObject.owner == authentication.name")
	public void addBook(List<Book> books);
}
 
filterObject is built-in object on which filter operation is performed. In this declaration, for the first method getBooks() we have used @PreAuthorize and @PostFilter. Before executing method, user is authorized on the basis of role and then after executing, the returned object is filtered on the basis of owner. Second method addBook() is only using @PreFilter on the basis of owner. Find the implementation class of IBookService.
BookService.java
package com.concretepage.service;
import java.util.ArrayList;
import java.util.List;
import com.concretepage.bean.Book;
public class BookService implements IBookService {
	@Override
	public List<Book> getBooks() {
		Book b1 = new Book("A","rahim");
		Book b2 = new Book("B","ram");
		Book b3 = new Book("C","rahim");
		Book b4 = new Book("D","ram");
		List<Book> books = new ArrayList<Book>();
		books.add(b1);
		books.add(b2);
		books.add(b3);
		books.add(b4);
		return books;
	}
	@Override
	public void addBook(List<Book> books) {
		System.out.println("Books Added.");
		for(Book b: books){
			System.out.println(b.getName()+":"+b.getOwner());
		}
	}
}
 
Find the spring security configuration for the users. To use @PreFilter and @PostFilter in Spring Security, we need to configure
<global-method-security pre-post-annotations="enabled"/>
 
We have configured two users ram and rahim. ram has ROLE_READ and ROLE_WRITE rights whereas rahim has ROLE_READ rights.
security-config.xml
  <http auto-config="true" use-expressions="true">
   <intercept-url pattern="/login" access="hasAnyRole('ROLE_READ','ROLE_WRITE')" />
   <logout logout-success-url="/login" />
  </http>
  <authentication-manager>
  <authentication-provider>
   <user-service>
	<user name="ram" password="con1234" authorities="ROLE_READ,ROLE_WRITE" />
	<user name="rahim" password="con1234" authorities="ROLE_READ" />
  </user-service>
  </authentication-provider>
  </authentication-manager>
  <global-method-security pre-post-annotations="enabled"/>
  <beans:bean name="bookService" class="com.concretepage.service.BookService"/>
 
In the controller on the basis of role we are calling BookService method, so that no access denied error is caught.
LoginController.java
package com.concretepage.security.controller;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.concretepage.bean.Book;
import com.concretepage.service.IBookService;
@Controller
@RequestMapping("/login")
public class LoginController {
	@Autowired
	public IBookService bookService;
	@RequestMapping(method = RequestMethod.GET)
	public String success(ModelMap map) {		
		Book b1 = new Book("A","rahim");
		Book b2 = new Book("B","ram");
		Book b3 = new Book("C","rahim");
		Book b4 = new Book("D","ram");
		List<Book> books = new ArrayList<Book>();
		books.add(b1);
		books.add(b2);
		books.add(b3);
		books.add(b4);
		if(hasRole("ROLE_WRITE")){
		  bookService.addBook(books);
		}
		if(hasRole("ROLE_READ")){
		  List<Book> bks = bookService.getBooks();
		  System.out.println("Books we got.");
		  for(Book b: bks){
				System.out.println(b.getName()+":"+b.getOwner());
		  }
		}
		map.addAttribute("msg", "Done Successfully");
		return "success";
	}  
	private boolean hasRole(String role) {
		Collection<GrantedAuthority> authorities = (Collection<GrantedAuthority>)SecurityContextHolder.getContext().
				getAuthentication().getAuthorities();
	    boolean hasRole = false;
	    for (GrantedAuthority authority : authorities) {
	    	hasRole = authority.getAuthority().equals(role);
	      if (hasRole) {
	    	  break;
	      }
	    }
	    return hasRole;
	  }
}
 
Book.java
package com.concretepage.bean;
public class Book {
	private String name;
	private String owner;
	public Book(String name,String owner){
		this.name = name;
		this.owner = owner;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getOwner() {
		return owner;
	}
	public void setOwner(String owner) {
		this.owner = owner;
	}
}
 
Now check the output by running the application. Download the source code which we are providing at the end of the blog. Use the URL as http://localhost:8080/SpringSecurity/login.
@PreFilter and @PostFilter in Spring Security
Login with ram/con1234, you will get below log on your console. What we need to pay attention is that list contains books for ram and rahim but ram will add and get only his books.
Books Added.
B:ram
D:ram
Books we got.
B:ram
D:ram
 
Login with rahim/con1234, you will get below log on your console. List contains books for ram and rahim, but it is filtered and rahim can only get his books.
Books we got.
A:rahim
C:rahim
 
Download Complete Source Code
POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS
comments powered by Disqus


Copyright ©2017 concretepage.com, all rights reserved |Privacy Policy | Contact Us