@sltay

Почему MockMVC игнорирует Security?

У меня есть следующая конфигурация Spring Security
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // для включения аннотации PreAuthorize
@SuppressWarnings("deprecation")
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    private final DetailsService userDetailsService;

    @Autowired
    public SpringSecurityConfig(DetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .antMatchers("/main").hasAnyRole("USER", "ADMIN") //указываем что в /main могут попасть только роли USER и ADMIN
                .antMatchers("/auth/login", "/auth/registration", "/error", "/api").permitAll() //в логин, регистарцию и ошибку могут попасть все
                .antMatchers("/css/**", "/js/**", "/images/**").permitAll()
                .and()
                .formLogin().loginPage("/auth/login") //указываем НЕ стандартную страницу логина, а кастомную
                .loginProcessingUrl("/processor_login") // action который перенаправляет нас при попытке залогиниться
                .defaultSuccessUrl("/", true) // если авторизовался
                .failureUrl("/auth/login?error") //если нет
                .and()
                .logout().logoutUrl("/logout").logoutSuccessUrl("/auth/login");//адрес для логаута
    }
    @Override
    public void configure(WebSecurity web) {
        web.ignoring()
                .antMatchers(
                        "/css/**", "/fonts/**",
                        "/images/**");
    }
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

}


И контроллер + тест к нему

@SpringBootTest
@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:/SQL/GetFriendsList.sql")
@Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:/SQL/DeleteFriendsList.sql")
public class ControllersTest {
    @Autowired
    WebApplicationContext webApplicationContext;
    private MockMvc mock;

    @BeforeEach
    public void initMock(){
        mock = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

 @Test
    @WithMockUser(username = "testUsername", password = "123123")
    public void testFriends() throws Exception {
        mock.perform(get("/main/friends")).andExpect(status().isOk());
    }
    @Test
    public void testUnAuthError() throws Exception {
        mock.perform(get("/main/friends")).andExpect(status().is3xxRedirection());
    }


@GetMapping("/friends")
    public String getFriendsList(Model model) {
   Optional<User> user = userService.findUser(SecurityContextHolder.getContext().getAuthentication().getName());
    //some useful staff
}


Проблема в том, что исходя из конфига секьюрити, по адресу /main могут пройти лишь авторизованные пользователи, но во втором тесте (который без @WithMockUser) Mock-объект не попадает в редирект из-за ошибки, а валится об NullPointerException, пытаясь получить из контекста имя пользователя в первой строке метода контроллера. Как заставить MockMVC не игнорировать Security?
  • Вопрос задан
  • 35 просмотров
Решения вопроса 1
@sltay Автор вопроса
Оказалось, что я неправильно понял смысл .antMatchers("/main")
я подумал что все последующие запросы из /main (/main/friends например) будут тоже заблокированы, но нет, надо указывать все возможные запросы
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы