173

It's not clear for me what is the difference in spring security between :

 @PreAuthorize("hasRole('ROLE_USER')")
 public void create(Contact contact)

And

@Secured("ROLE_USER")
public void create(Contact contact)

I understand PreAuthorize can work with spring el but in my sample, is there a real difference ?

cdeszaq
  • 30,869
  • 25
  • 117
  • 173
Jerome VDL
  • 3,376
  • 4
  • 32
  • 33

5 Answers5

189

The real difference is that @PreAuthorize can work with Spring Expression Language (SpEL). You can:

  • Access methods and properties of SecurityExpressionRoot.
  • Access method arguments (requires compilation with debug info or custom ParameterNameDiscoverer):

    @PreAuthorize("#contact.name == principal.name")
    public void doSomething(Contact contact)
    
  • (Advanced feature) Add your own methods (override MethodSecurityExpressionHandler and set it as <global-method-security><expression-handler ... /></...>).
Ivar
  • 4,350
  • 2
  • 27
  • 29
axtavt
  • 239,438
  • 41
  • 511
  • 482
63

If you wanted to do something like access the method only if the user has Role1 and Role2 then you would have to use @PreAuthorize

@PreAuthorize("hasRole('ROLE_role1') and hasRole('ROLE_role2')")

Using

@Secured({"role1", "role2"}) // is treated as an OR
splash
  • 13,037
  • 1
  • 44
  • 67
arnabmitra
  • 903
  • 9
  • 19
48

Simply, @PreAuthorize is newer than @Secured.

So I say it is better to use @PreAuthorize as it is "expression-based" and you can use expressions like hasRole, hasAnyRole, permitAll, etc.

To learn about expressions, see these example expressions.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
Dennis
  • 547
  • 4
  • 4
20

@PreAuthorize is different, it is more powerful than @Secured.

  • The older @Secured annotations did not allow expressions to be used.

  • Starting with Spring Security 3, the more flexible annotations @PreAuthorize and @PostAuthorize (as well as @PreFilter and @PostFilter) are preferred, as they support Spring Expression Language (SpEL) and provide expression-based access control.

  • @Secured("ROLE_ADMIN") annotation is the same as @PreAuthorize ("hasRole('ROLE_ADMIN')").

  • The @Secured({"ROLE_USER","ROLE_ADMIN") is considered as ROLE_USER OR ROLE_ADMIN.

so you cannot express the AND condition using

@Secured. You can define the same with @PreAuthorize("hasRole('ADMIN') OR hasRole('USER')"), which is easier to understand. You can express AND, OR, or NOT(!) as well.

@PreAuthorize("!isAnonymous() AND hasRole( 'ADMIN')")

becher henchiri
  • 618
  • 4
  • 10
  • 1
    As you reverted my edit, are you saying that there is no error in this `"hasRole('ADMIN OR hasRole('USER')"`? – rigon Oct 04 '19 at 16:32
11
+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------------------------------+
|                                               |                         @Secured                         |                         @PreAuthorize                           |
+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------------------------------+
| Spring EL expressions                         | Does'nt supports.                                        | Supports                                                        |
+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------------------------------+
| Multiple roles conjunctions with AND operator | Does'nt supports.(If there are multiple roles defined    | Supports                                                        |
|                                               |they will be automatically combined with OR operator)     |                                                                 |
+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------------------------------+
| To enable annotation                          | Add following line to spring-security.xml                | Add following line to spring-security.xml                       |
|                                               | <global-method-security secured-annotations="enabled" /> | <global-method-security pre-post-annotations="enabled"/>        |
+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------------------------------+
| Example                                       | @Secured({ROLE_ADMIN , ROLE_USER})                       | @PreAuthorize("hasRole('ROLE_USER') and hasRole('ROLE_ADMIN')") |
|                                               | public void addUser(UserInfo user){...}                  | public void addUser(UserInfo user){...}                         |
+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------------------------------+
Joby Wilson Mathews
  • 10,528
  • 6
  • 54
  • 53