Spring Security. Нет доступа к странице авторизованному пользователю (Forbidden 403)

URL /user должны посетить только авторизованные пользователи, которые имеют роль USER. Описание проблемы:

  • Если не авторизоваться и сразу перейти на /user, то посетитель будет перенаправлен на страницу логина (тут всё как надо)
  • После авторизации пользователь перенаправляется на /user, только вместо приветствия получает Forbidden 403 Whitelabel Error Page

Мой код

    @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 не изменяет заданную строку и поэтому пользователь будет успешно авторизован.

→ Ссылка