Spring Security Java Config не генерирует URL-адрес выхода из системы

Я использую Spring 4.0.5.RELEASE и Spring Security 3.2.4.

Я пытаюсь создать простой образец приложения, используя конфигурацию Java (на основе образцов Spring). Приложение запускается, и аутентификация работает правильно, то есть я перенаправляюсь на форму входа при доступе к защищенному URL-адресу /settings/profile

Однако URL-адрес /logout не сгенерирован? если я нажму localhost:8080/logout, я получу 404.

Я использовал аналогичный код в предыдущем проекте, так что, может быть, это как-то связано с версиями?

Вот моя конфигурация безопасности

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("password").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/settings/**").hasRole("ROLE_ADMIN")
                    .and()
                .formLogin()
                    .and()
                .logout()
                    .deleteCookies("remove")
                    .invalidateHttpSession(true)
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/logout-success")
                .permitAll();
    }
}

Вот мой WebAppInitializer для начальной загрузки приложения

 public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { SecurityConfig.class , MvcConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
         return new String[] {"/"};
    }
}

и, наконец, мой MvcConfig

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"web"})
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

person Ayub Malik    schedule 08.06.2014    source источник


Ответы (1)


По умолчанию POST-запрос требуется для URL-адреса выхода. Для выхода из системы по GET-запросу вам необходимо:

http
      .logout()
          .logoutRequestMatcher(new AntPathRequestMatcher("/logout"));

Или, если вы хотите поддерживать PUT или другой метод, передайте это как параметр:

http
      .logout()
          .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "PUT"));

См. документы: http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/ (раздел 6.5.3. Выход из системы)

person Evgeni Dimitrov    schedule 08.06.2014
comment
Вы случайно не знаете, как настроить это с помощью xml? - person yglodt; 11.05.2015
comment
Я столкнулся с аналогичной проблемой. Я выполняю POST /appContextRoot/logout и передаю необходимый заголовок XSRF-TOKEN, но все равно получаю 404. Что еще? - person Kamal Joshi; 08.11.2015
comment
Стоит отметить, что это не лучшая практика, поскольку она делает вас уязвимыми для потенциальных CSRF-атак. Из JavaDoc: The URL that triggers log out to occur (default is "/logout"). If CSRF protection is enabled (default), then the request must also be a POST. This means that by default POST "/logout" is required to trigger a log out. If CSRF protection is disabled, then any HTTP method is allowed. It is considered best practice to use an HTTP POST on any action that changes state (i.e. log out) to protect against CSRF attacks. ... - person Matthew Smith; 04.01.2016
comment
во многих случаях, как и в старом JSP, использование обычной ссылки для выхода из системы всегда будет отправлять запрос GET, но вы можете использовать форму в качестве обходного пути, как описано здесь: stackoverflow.com/questions/6791238/ - person Gregor; 01.02.2019
comment
еще лучше, без JavaScript, но с оформлением кнопки в виде ссылки: stackoverflow.com/a/22076149/160799 - person Gregor; 01.02.2019