Using
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
my example works fine. For example for
http.authorizeRequests()
// ...
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.and().formLogin()
.and().exceptionHandling().accessDeniedPage("/Access_Denied");
If I have changed inMemoryAuthentication to spring jdbc default - i got an role issue than.
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
I sure I configured db and schema using spring recommendations (to be able to use default jdbc authentication).
In debug mode I can see result of loading from db in the
org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl
#loadUserByUsername(username)[line 208]
return createUserDetails(username, user, dbAuths);
It returns similar result with in memory configuration:
org.springframework.security.core.userdetails.User@183a3:
Username: dba;
Password: [PROTECTED];
Enabled: true;
AccountNonExpired: true;
credentialsNonExpired: true;
AccountNonLocked: true;
Granted Authorities: ADMIN,DBA
As you can see it loads correspond Granted Authorities, but http request redirects me to .accessDeniedPage("/Access_Denied"). I confused because It should work for user like time before.
I do not use spring boot in my project. My logs does not contain any configuration of jdbc errors. I have spend a lot of time to investigate details and my ideas have just finished. Do you think I need add to build some cache libraries or something else?
You can see see what happened enabling the logging. In your
application.properties
add:There are 2 gotchas in play here.
The first is that when using
hasRole('ADMIN')
that first a check is done if it starts with the role prefix (for which the default isROLE_
) if not the passed in role is prefix with it (see also the reference guide). So in this case the actual authority checked isROLE_ADMIN
and notADMIN
as you expect/assume.The second is that when using the in memory option the
roles
method does the same as mentioned here. It checks if the passed in roles start with the role prefix and if not adds it. So in your sample with the in memory one you end up with authoritiesROLE_ADMIN
andROLE_DBA
.However in your JDBC option you have authorities
ADMIN
andDBA
and hence thehasRole('ADMIN')
check fails becauseROLE_ADMIN
isn't equal toADMIN
.To fix you have several options.
hasRole
usehasAuthority
the latter doesn't add the role prefix and for the in memory option useauthorities
instead ofroles
.ROLE_
Using
hasAuthority
First change the configuration of the in memory database to use
authorities
instead ofroles
.next change your expressions as well
Prefix with
ROLE_
In the script that inserts the authorities prefix the authorities with
ROLE_
.Remove the default role prefix
This is a bit tricky and is extensivly described in [the migration guide].
There is no easy configuration option and requires a
BeanPostProcessor
.