Spring Security. Нет доступа к странице авторизованному пользователю (Forbidden 403)
URL /user должны посетить только авторизованные пользователи, которые имеют роль USER. Описание проблемы:
- Если не авторизоваться и сразу перейти на /user, то посетитель будет перенаправлен на страницу логина (тут всё как надо)
- После авторизации пользователь перенаправляется на /user, только вместо приветствия получает Forbidden 403

Мой код
@Bean
public SecurityFilterChain filter(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/").permitAll()
.requestMatchers("/user").hasRole("USER")
.requestMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin((form) -> form.permitAll())
.logout((logout) -> logout.permitAll())
.build();
}
В SecurityFilterChain я описал то, что страницу /user могут посещать только имеющие роль USER.
Ниже мой UserDetailsService.
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null)
throw new UsernameNotFoundException("Cannot find user " + username);
return new CustomUserDetails(user, roleRepository.findByUserId(user));
}
}
public class CustomUserDetails implements UserDetails {
private final User user;
private final Collection<Role> roles;
public CustomUserDetails(User user, Collection<Role> roles) {
this.user = user;
this.roles = roles;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles.stream()
.map(role -> new SimpleGrantedAuthority(role.getRoleName()))
.collect(Collectors.toCollection(ArrayList::new));
}
// ...
}
На главной странице я поставил такую проверку, которая показывает, что авторизованный пользователь действительно имеет роль USER
@GetMapping
public String home(@AuthenticationPrincipal UserDetails userDetails) {
System.out.println("ROLE: " + userDetails.getAuthorities().stream().findFirst().get().getAuthority());
return "home";
}
Возможно я что-то упустил?
Ответы (1 шт):
Автор решения: Arkady
→ Ссылка
Эту проблему можно решить, использовав hasAuthority вместо hasRole.
При использовании hasRole Spring к заданной строке добавляет префикс ROLE_ и поэтому проверка не проходит. Метод hasAuthority не изменяет заданную строку и поэтому пользователь будет успешно авторизован.