2016-03-07 2 views
0

Мой сайт позволяет пользователям, не прошедшим проверку подлинности (анонимным), выполнять поиск контента, для которого требуется аутентификация для просмотра. В настоящее время, когда они нажимают на ссылку, чтобы просмотреть сведения об одном из элементов контента на странице результатов поиска, Spring Security правильно идентифицирует пользователя как не прошедшую проверку подлинности и отображает страницу входа. Тем не менее, я хотел бы вмешаться и вместо этого отобразить страницу, чтобы побудить анонимного пользователя зарегистрироваться на сайте. Я проследил, что происходит в цепочке фильтров, но мне не ясно, должен ли я расширять существующий фильтр или обработчик или создавать собственный фильтр или обработчик. Если это позже, я не уверен, куда он должен идти.Spring Security 4 перехват анонимного пользователя AccessDeniedException

Когда я запускаю это через отладку я вижу следующее происходящий:

  • ExceptionTranslationFilter.doFilterFilterSecurityInterceptor выполняет, который определяет, что страница детали требует аутентификации (возвращает -1 голос и бросает AccessDeniedException)
  • ExceptionTranslationFilter уловов исключение, определяет, что пользователь является анонимным, и называет authenticationEntryPoint, в этом случае LoginUrlAuthenticationEntryPoint
  • LoginUrlAuthenticationEntryPoint вызывает DefaultRedirectStrategy, который перенаправляет пароль пользователя ge

Итак, в основном мне нужно переопределить перенаправление на страницу входа для этого одного варианта использования. Мое лучшее предположение заключается в создании настраиваемого фильтра, который проверяет комбинацию анонимного пользователя, который обращается к этой конкретной странице подробностей, и перенаправляет на страницу соединения, вставляя фильтр в цепочку после ExceptionTranslationFilter. Или это полный избыток для обработки перенаправления одной страницы, и есть ли более простой способ сделать это?

+0

Нет, создать и ввести пользовательские 'AuthenticationEntryPoint' один, который решил, на какую страницу для перенаправления вместо страницы входа по умолчанию. Не взламывайте фильтр, просто создайте подходящую точку входа. –

+0

@ M.Deinum Спасибо за подсказку - он отлично работал! Единственный побочный эффект - члены сайта будут видеть страницу соединения, если они еще не вошли в систему, но на самом деле это нормально, так как словосочетание на странице охватывает эту ситуацию. – LWK69

ответ

0

Для всех, кому это интересно, вот код для пользовательской точки входа auth, заимствования из LoginUrlAuthenticationEntryPoint и ExceptionTranslationFilter.

public class CustomAuthLoginEntryPoint extends LoginUrlAuthenticationEntryPoint { 

    private final Logger logger = LoggerFactory.getLogger(getClass()); 

    private PortResolver portResolver = new PortResolverImpl(); 
    private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); 
    private RequestCache requestCache = new HttpSessionRequestCache(); 
    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); 
    private String joinPageUrl; 

    public CustomAuthLoginEntryPoint(String loginFormUrl) { 
     super(loginFormUrl); 
    } 

    @Override 
    public void commence(HttpServletRequest request, HttpServletResponse response, 
      AuthenticationException authException) throws IOException, ServletException { 
     logger.debug("commence"); 

     String redirectUrl = null; 

     if (!StringUtils.isBlank(joinPageUrl)) { 
      Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
      if (auth == null || trustResolver.isAnonymous(auth)) { 
       SavedRequest savedRequest = requestCache.getRequest(request, response); 
       redirectUrl = savedRequest.getRedirectUrl(); 

       if (redirectUrl.indexOf("viewDetail") > 0) { 
        String joinPageUrl = buildRedirectUrlToJoinPage(request); 
        logger.debug("Redirecting to '" + joinPageUrl + "'"); 
        redirectStrategy.sendRedirect(request, response, joinPageUrl); 
        return; 
       }    
      } 
     } 

     super.commence(request, response, authException); 
    } 

    protected String buildRedirectUrlToJoinPage(HttpServletRequest request) { 

     int serverPort = portResolver.getServerPort(request); 
     String scheme = request.getScheme(); 

     RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder(); 

     urlBuilder.setScheme(scheme); 
     urlBuilder.setServerName(request.getServerName()); 
     urlBuilder.setPort(serverPort); 
     urlBuilder.setContextPath(request.getContextPath()); 
     urlBuilder.setPathInfo(joinPageUrl); 

     return urlBuilder.getUrl(); 
    } 

    public void setJoinPage(String joinPageUrl) { 
     this.joinPageUrl = joinPageUrl; 
    } 
} 

Я добавил это к моему WebSecurityConfigurerAdapter:

@Bean 
public CustomAuthLoginEntryPoint customAuthLoginEntryPoint() { 
    CustomAuthLoginEntryPoint entryPoint = new CustomAuthLoginEntryPoint("/user/login"); 
    entryPoint.setJoinPage("/user/join"); 
    return entryPoint; 
} 

и HTTP настроить:

.exceptionHandling() 
     .accessDeniedHandler(accessDeniedHandler()) 
     .authenticationEntryPoint(customAuthLoginEntryPoint()) 
Смежные вопросы