I am trying to convert a Spring Security 3 @Secured("admin") annotation into Spring Security 4 compatible fashion.
This is my usersService.java
@PreAuthorize("hasAuthority('admin')")
public List<User> getAllUsers() {
return usersDao.getAllUsers();
}
Then in security-context.xml
I have:
<security:intercept-url pattern="/admin" access="permitAll" />
...
<security:global-method-security pre-post-annotations="enabled" />
getAllUsers()
is called by a LoginController.java
@RequestMapping("/admin")
public String showAdmin(Model model) {
List<User> users = usersService.getAllUsers();
model.addAttribute("users", users);
return "admin";
}
In mySql database, there are two tables, users and authorities. authorities
has 2 columns, username and authority. administrator
has authority admin
.
Now if I trie to access /admin
, I will be redirected to /login
, but after I log in with administrator
, I still get "access denied".
I think I must have missed something very basic but as I am new to Spring, I could not figure it out. Any help would be appreciated. Thanks.
Update: I tried changing the annotation to @PreAuthorize("hasRole('ROLE_ADMIN')") and I also changed the "authority" column in mySql for admin from "admin" to "ROLE_ADMIN" but it still gives me 403. I did not have much faith on this because before this error, I had to change hasRole('admin')
in securityContext.xml
to hasAuthority('admin')
.
The most obviously useful annotation is @PreAuthorize which decides whether a method can actually be invoked or not. For example (from the “Contacts” sample application) @PreAuthorize("hasRole('ROLE_USER')") public void create(Contact contact);
The real difference is that @PreAuthorize can work with Spring Expression Language (SpEL). You can: Access methods and properties of SecurityExpressionRoot . (Advanced feature) Add your own methods (override MethodSecurityExpressionHandler and set it as <global-method-security><expression-handler ... /></...> ).
The global method security functionality is disabled by default. To enable it, you use the @EnableGlobalMethodSecurity annotation over the configuration class of your application. You can apply authorization rules that the application checks before the call to a method.
Although it's late, nevertheless
hasRole(...)
set a prefix for the the content - the default one is ROLE_
hasAuthority(...)
checks the content WITHOUT a prefix, i.e. just the pure content
You should add in Spring security
@EnableGlobalMethodSecurity(prePostEnabled = true)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With