Это связано с тем, что фильтр, который генерирует страницу входа, выше, чем фильтр, который обрабатывает сопоставления 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
, что является гораздо более подходящим кандидатом.