Как сделать аннулирование запомнить меня при выходе? - PullRequest
0 голосов
/ 09 января 2019

Ну, я не реализую PersistentTokenBasedRememberMeServices, поэтому я не могу использовать .logout(request, response, auth). Но я использую JdbcTokenRepositoryImpl, чтобы использовать PersistentTokenRepository для функции запомнить меня.

LogoutController:

@Controller
public class LogoutController {

    @RequestMapping(value = {"/logout"}, method = RequestMethod.GET)
    public String logout() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if(auth != null) {
            SecurityContextHolder.getContext().setAuthentication(null);
        }

        return "redirect:/login?logout";
    }
}

Конфигурация безопасности:

@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "/playground").hasAnyRole("ROOT", "MODER", "USER")
            .antMatchers("/users/**").hasAnyRole("ROOT", "MODER")
        .and()
            .formLogin().loginPage("/login").loginProcessingUrl("/login").failureHandler(customAuthenticationFailureHandler())
        .and()
            .rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).userDetailsService(userDetailsService)
        .and()
            .logout().logoutUrl("/logout");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setPasswordEncoder(passwordEncoder());
        authProvider.setUserDetailsService(userDetailsService);
        return authProvider;
    }

    @Bean
    public AuthenticationFailureHandler customAuthenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        return jdbcTokenRepository;
    }

Когда я вхожу в систему, помни меня, я не могу выйти из нее. Я думаю, из-за функции запомнить меня. Что я должен добавить в LogoutController для правильного процесса выхода из системы?

Примечание: дело в том, что если я просто использую метод POST при выходе из системы, то он отлично работает, но я хотел бы использовать метод GET и, следовательно, мне нужно создать контроллер выхода из системы для выполнения метод get.

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Подводя итог.

Мне удалось протестировать несколько способов, и вот что я получил:

  1. Как предложил М. Дейнм в комментариях, возможно не использовать контроллер и, тем не менее, выйти из системы с запросом GET. Вот оно.

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

  1. Как предложил Эндрю Саша в разделе ответов, вы можете отключить csrf, поскольку он намеренно запрещает использование GET-запроса. И теперь вы можете использовать GET-запрос для выхода из системы даже без использования какого-либо контроллера.

http.csrf().disable()

  1. Если вы все еще хотите использовать контроллер, нет из следующих вещей поможет вам

.deleteCookies("remember-me", "JSESSIONID")
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/")

(я не уверен, но мне кажется, что он не работает, потому что вы выполняете запрос GET и используете свой контроллер для контроля выхода из системы)

  1. Итак, вы можете сделать это программно

Во-первых, вы добавили имя для помнить меня cookie в конфигурации безопасности Spring:

rememberMe().rememberMeCookieName("remember-me")

А затем в контроллер выхода из системы добавьте следующее:

String cookieName = "remember-me";
Cookie cookie = new Cookie(cookieName, null);
cookie.setMaxAge(0);
cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/");
response.addCookie(cookie);

Единственная проблема в том, что вам нужно вручную удалить запись из таблицы persistent_logins

(Чтобы получить запрос и ответ, просто передайте их в метод public void logout(HttpServletRequest request, HttpServletResponse response)

  1. Можно использовать запрос POST, но использовать его как ссылку с помощью JavaScript или даже простого HTML и CSS.

Решения для этого вы можете найти в этой теме .

Так что у нас здесь?

Подводя итог всему вышесказанному, я могу сказать, что если вам нужен контроллер, вы должны программно написать все самостоятельно (кто-то скажет, что это изобретение колеса).

Тем не менее, можно использовать запрос GET, но без контроллера, который описан в 1-й и 2-й позициях списка.

(Последствия использования запроса GET описаны в Документация CSRF , и он не рекомендует использовать запрос GET из-за его неуязвимости.)

Итак, последнее, что я решил сделать своим любимым, это сделать POST-запрос похожим на GET-запрос (используйте его как ссылку) с помощью JS или HTML и CSS. И поскольку вы используете POST-запрос, вы как бы получаете защиту CSRF.

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 09 января 2019

Попробуйте отключить crsf (http.csrf().disable()).

Реализация по умолчанию в фильтре выхода из системы безопасности:

        if (http.getConfigurer(CsrfConfigurer.class) != null) {
            this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
        }
        else {
            this.logoutRequestMatcher = new OrRequestMatcher(
                new AntPathRequestMatcher(this.logoutUrl, "GET"),
                new AntPathRequestMatcher(this.logoutUrl, "POST"),
                new AntPathRequestMatcher(this.logoutUrl, "PUT"),
                new AntPathRequestMatcher(this.logoutUrl, "DELETE")
            );
        }

Как вы можете видеть, включен ли ваш Csrf (по умолчанию он включен, даже если вы перезаписали protected void configure(HttpSecurity http)), тогда будет работать только метод POST, если не все работают.

Кстати: вы уверены, что ваш запрос достигает LogoutController, потому что я думаю, что он использует стандартный механизм выхода из системы безопасности пружины? (Чтобы отключить его, выполните http.logout().disable(), так же, как csrf, он включен по умолчанию)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...