@PreAuthorize and @PostAuthorize in Spring Security
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); }
@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"/>
@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"); } }
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; } }
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"; } }


