I'm trying to use Spring Security in my project, here is the code:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Auto-generated method stub
//super.configure(auth);
//auth.inMemoryAuthentication().withUser("admin").password("1111").roles("USER");
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username, password, 1 from users where username=?")
.authoritiesByUsernameQuery("select users_username, roles_id from roles_users where users_username=?")
.rolePrefix("ROLE_");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
http
.httpBasic();
http
.authorizeRequests()
.anyRequest().authenticated();
http
.authorizeRequests()
.antMatchers("/users/all").hasRole("admin")
.and()
.formLogin();
http
.exceptionHandling().accessDeniedPage("/403");
}
Here is the problem:
Imagine we have two users (one with the user
role and the other one with the admin
role) in our database one admin and the second is a user, the problem is when I connect as user (which has only user
role) it can access to admin resources (and this is not the expected behavior).
I think the problem in this query:
"select username, password, 1 from users where username=?"
According that username
is the primary key?
If anyone has an idea how I can resolve this problem?
Your first matcher anyRequest()
is always applied, because the order of matchers is important, see HttpSecurity#authorizeRequests
:
Note that the matchers are considered in order. Therefore, the following is invalid because the first matcher matches every request and will never get to the second mapping:
http.authorizeRequests().antMatchers("/**").hasRole("USER").antMatchers("/admin/**") .hasRole("ADMIN")
Your modified and simplified configuration:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/users/all").hasRole("admin")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.exceptionHandling().accessDeniedPage("/403");
}
The problem is with the ordering of your rules when you configure your HttpSecurity
. What's happening is when the request comes in and hits the
authorizeRequests().anyRequest().authenticated()
and since the user is authenticated it never makes it to the
.antMatchers("/users/all").hasRole("admin")
Here is an example of how you can configure it:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/public").permitAll()
.antMatchers("/user").hasRole("USER")
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.exceptionHandling().accessDeniedPage("/403");
}
It uses the chain of responsibility pattern. It will go through the chain of rules until it finds a rule that matches. Any rules that come after the rule that matches are never reached. Generally when writing the rules for authenticated requests, the more specific rule will come first.
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