Перенаправление с / логина на / для аутентифицированных пользователей - PullRequest
0 голосов
/ 14 мая 2018

У нас есть приложение Spring Security, которое в основном обрабатывает аутентификацию через страницу Thymeleaf перед передачей пользователя в приложение Angular. В настоящее время, если пользователь уже вошел в систему, пытается зайти в / login, он переводит его на страницу входа в систему для заполнения - если он зайдет просто / тогда, он будет правильно перенаправлен на нашу панель управления / домашнюю страницу. Мы просто хотим иметь возможность перенаправить / войти в систему / для аутентифицированных пользователей.

Вот конфигурация HttpSecurity, которую мы используем, и я предполагаю, что для достижения этой цели потребуется только простая модификация:

@Override
public void configure( HttpSecurity http ) throws Exception
{
    // @formatter:off
    http
            .cors()
            .and()
            .exceptionHandling()
            .accessDeniedHandler( accessDeniedHandler() )
            .authenticationEntryPoint( new RestAuthenticationEntryPoint() )
            .and()
            .authorizeRequests()
            .antMatchers( "/login" ).permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage( "/login" )
            .failureHandler( internalAuthFailureHandler )
            .successHandler( internalAuthSuccessHandler )
            .permitAll()
            .and()
            .logout()
            .logoutUrl( "/logout" )
            .logoutSuccessUrl( "/login?logout" )
            .permitAll()
            .and()
            .csrf()
            .csrfTokenRepository( CookieCsrfTokenRepository.withHttpOnlyFalse() );
    // @formatter:on
}

Я пытался использовать .not (). Authenticated () для страницы / login, но не смог понять это, и я не понимаю, какая документация должна помочь в этом.

1 Ответ

0 голосов
/ 14 мая 2018

Это связано с тем, что фильтр, который генерирует страницу входа, выше, чем фильтр, который обрабатывает сопоставления HttpSecurity, поэтому использование .not().authenticated() или других традиционных методов не работает для вас.

Сначала я создалпользовательский класс фильтра, я назвал его LoginPageFilter:

class LoginPageFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (SecurityContextHolder.getContext().getAuthentication() != null
              && SecurityContextHolder.getContext().getAuthentication().isAuthenticated()
              && ((HttpServletRequest)request).getRequestURI().equals("/login")) {
            System.out.println("user is authenticated but trying to access login page, redirecting to /");
            ((HttpServletResponse)response).sendRedirect("/");
        }
        chain.doFilter(request, response);
    }
}

Выше будет проверено, аутентифицирован ли текущий пользователь и является ли текущий путь /login.

Если он, тоэто перенаправит его на /.В противном случае продолжайте идти по цепочке фильтров.

После этого вам нужно добавить фильтр в существующую цепочку фильтров, но вы не сможете его нигде добавить.Это должно быть после того, как аутентификация была разрешена идентификатором сеанса (в противном случае SecurityContextHolder.getContext().getAuthentication() всегда будет возвращать ноль), и это должно быть до существующего фильтра, чем разрешает доступ к странице входа в систему.

ЛучшийКандидат до DefaultLoginPageGeneratingFilter, который является фильтром, генерирующим страницу входа в систему.

Чтобы добавить пользовательский фильтр в этой позиции, вам нужно добавить его в верхней части вашего configure(HttpSecurity http) метода:

http.addFilterBefore(new LoginPageFilter(), DefaultLoginPageGeneratingFilter.class);

В вашем примере это выглядело бы следующим образом:

@Override
public void configure( HttpSecurity http ) throws Exception
{
    http.addFilterBefore(new LoginPageFilter(), DefaultLoginPageGeneratingFilter.class);
    // @formatter:off
    http
            .cors()
            .and()
            .exceptionHandling()
            .accessDeniedHandler( accessDeniedHandler() )
            .authenticationEntryPoint( new RestAuthenticationEntryPoint() )
            .and()
            .authorizeRequests()
            .antMatchers( "/login" ).permitAll()
            // ...
    // @formatter:on
}

Я загрузил свой полный класс на тот случай, если вам нужно посмотреть поближе:

https://gist.github.com/TwinProduction/5e2e320f5f87c009c330828c3e34a6dc

Удачи!

Обновление

По предложению @ dur я заменил UsernamePasswordAuthenticationFilter на DefaultLoginPageGeneratingFilter, что является гораздо более подходящим кандидатом.

...