Reputation: 1
Used Spring Boot 2 + Spring Security Starter.
Authorizes users, but for some reason gives an error 403.
I tried to configure in different ways, but it does not work.
After successful authorization (the loadUserByUsername
method works fine) it shows 403 on all pages with the / admin prefix, and before authorization, switching to any page with this prefix leads to a redirect to / login
@Controller
public class AdminController {
@RequestMapping(value = "/admin", method = {GET, POST})
public String adminMainPage() {
return "redirect:/admin/article";
}
}
@Controller
@RequestMapping("/admin/article")
public class ArticleController {
@RequestMapping(value = "", method = {GET, POST})
public ModelAndView indexAdminPage(...){
...
}
}
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements UserDetailsService {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.userDetailsService(this)
.authorizeRequests()
.antMatchers("/", "/login",
"/login*", "/assets/**", "/lib/**", "/page.scripts/*").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("login")
.passwordParameter("password")
.successForwardUrl("/admin")
.permitAll()
.and()
.logout()
.deleteCookies("JSESSIONID")
.permitAll();
}
private Collection<? extends GrantedAuthority> adminGrantedAuthoritySet = new HashSet<>() {{
add(new SimpleGrantedAuthority("ADMIN"));
}};
private final UserRepository userRepository;
public WebSecurityConfig(UserRepository userRepository ) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
Optional<UserEntity> optionalUser = userRepository.findByLogin(login);
if (optionalUser.isEmpty()) {
throw new UsernameNotFoundException("User by login '" + login + "' not found");
} else {
UserEntity userEntity = optionalUser.get();
return new User(login, userEntity.getPassword(), adminGrantedAuthoritySet);
}
}
}
Upvotes: 0
Views: 290
Reputation: 4446
First, I will advice that you separate UserDetailsService from the WebSecurityConfig.
Have a separate class for UserDetailsService like
@Service("customCustomerDetailsService")
public class CustomCustomerDetailsService implements UserDetailsService {
@Autowired
private CustomerRepository customers;
@Override
public UserDetails loadUserByUsername(String email) {
return this.customers.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("Username: " + email + " not found"));
}
}
Then your UserEntity should implement UserDetails class where you set the authorities.See the answer //userdetails
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles.stream().map(SimpleGrantedAuthority::new).collect(toList());
}
@Override
public String getUsername() {
return this.getEmail();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Transient
private List<String> roles = Arrays.asList("ROLE_USER");
public List<String> getRoles() {
return roles;
}
Then you need DAOauthentication manager which makes use of the UserDetailsService like this:
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(encoder());
return authProvider;
}
@Bean
@Override
public UserDetailsService userDetailsService() {
return new CustomCustomerDetailsService();
}
I don't know think putting everything in the WebSecurityConfig is good practice and it will be complicated and prone to errors!
Upvotes: 0
Reputation: 6499
In Spring Security there is a distinction between a role
and an authority
.
A role
is an authority
that is prefixed with "ROLE_"
. In this example the authority "ROLE_ADMIN"
is the same as the role "ADMIN"
.
You are setting your admin authorities
to be a list of new SimpleGrantedAuthority("ADMIN")
, but you are restricting access to .hasAnyRole("ADMIN")
.
You need to change one of those configurations.
If you use .hasAnyRole("ADMIN")
, then you should change the admin authorities
list to use new SimpleGrantedAuthority("ROLE_ADMIN")
.
Otherwise, if you want your list to be new SimpleGrantedAuthority("ADMIN")
, then you should use .hasAnyAuthority("ADMIN")
.
Upvotes: 1