@PreAuthorize and @PostAuthorize in Spring Security

By Arvind Rai, November 27, 2019
Spring Security provides method level security using @PreAuthorize and @PostAuthorize annotations. This is expression-based access control.
The @PreAuthorize can check for authorization before entering into method. The @PreAuthorize authorizes on the basis of role or the argument which is passed to the method.
The @PostAuthorize checks for authrorisation after method execution. The @PostAuthorize authorizes on the basis of logged in roles, return object by method and passed argument to the method. For the returned object spring security provides built-in keyword i.e. returnObject.

Using @PreAuthorize and @PostAuthorize

Find the code for @PreAuthorize and @PostAuthorize in the interface of the service layer.
IBookService.java
package com.concretepage.service;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import com.concretepage.bean.Book;
public interface IBookService {
	@PreAuthorize ("hasRole('ROLE_WRITE')")
	public void addBook(Book book);

	@PostAuthorize ("returnObject.owner == authentication.name")
	public Book getBook();

	@PreAuthorize ("#book.owner == authentication.name")
	public void deleteBook(Book book);
} 
Look at the interface above, we have used @PreAuthorize and @PostAuthorize annotations. The authentication and principal keyword can directly be used to access user informations. The # is used to access argument of the method.
Now take attention on @PostAuthorize that built-in keyword returnObject has been used. Here returnObject is equivalent to Book instance returned by the method. Now find the Spring Security XML file.
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"/> 

Enable pre-post Annotations

To use @PreAuthorize and @PostAuthorize annotations in our Spring Security application, we need to enable pre-post annotations.
Find the code for XML configuration.Enable pre-post annotations using <global-method-security> namespace as given below.
<global-method-security pre-post-annotations="enabled"/> 
In case we are using Java configuration, then that class needs to be annotated with @EnableGlobalMethodSecurity as given below.
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
   ------
}

Complete Example

Now for the example, I have taken two roles ROLE_READ and ROLE_WRITE and two user ram and rahim. The ram is authorized with both roles whereas rahim is authorized with ROLE_READ. Find the Java files.
BookService.java
package com.concretepage.service;
import com.concretepage.bean.Book;
public class BookService implements IBookService {
	@Override
	public void addBook(Book book) {
		System.out.println("You have successfully added book.");		
	}
	@Override
	public Book getBook() {
		Book book = new Book("B", "ram");
		return book;
	}
	@Override
	public void deleteBook(Book book) {
	  System.out.println("Books deleted");		
	}
} 
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;
	}
} 
LoginController.java
package com.concretepage.security.controller;
import org.springframework.beans.factory.annotation.Autowired;
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");
		bookService.addBook(b1);
		bookService.getBook();
		Book b2 = new Book("B","ram");
		bookService.deleteBook(b2);
		map.addAttribute("msg", "Done Successfully");
		return "success";
	}  
} 
Download the source code from the link given at the end of the blog and use URL as http://localhost:8080/SpringSecurity/login . You will see the below UI.
@PreAuthorize and @PostAuthorize in Spring Security
When we try with ram, we will get success message.
@PreAuthorize and @PostAuthorize in Spring Security
Try with rahim user, we will get access HTTP Status 403 - Access is denied message.
@PreAuthorize and @PostAuthorize in Spring Security

Download Complete Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us