2014-10-05 2 views
4

Добрый день.Весенняя обувь + Весенняя безопасность: как подавить основную форму авторизации

Я использую Spring security в контексте загрузочного автозапуска Spring. Моя цель - настроить базовый auth таким образом, чтобы базовая форма авторизации стандартного браузера не отображалась на 401. Из Google я узнал, что для этого мне нужно изменить заголовок «WWW-Authenticate» по умолчанию на нечто иное, чем « Basic xxxxx ".

Чтобы сделать это, я объявил фильтр:

@Bean 
@Order(Integer.MAX_VALUE) 
public Filter customAuthFilter() { 
    return new Filter() { 

     @Override 
     public void init(FilterConfig fc) throws ServletException { 
     } 

     @Override 
     public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain fc) throws IOException, ServletException { 
      HttpServletRequest req = (HttpServletRequest) sreq; 
      HttpServletResponse resp = (HttpServletResponse) sresp; 

      fc.doFilter(req, resp); 
      log.info("filter"); 
      log.info("status " + resp.getStatus()); 
      if(resp.getStatus() == 401) { 
       resp.setHeader("WWW-Authenticate", "Client-driven"); 
      } 
     } 

     @Override 
     public void destroy() { 
     } 
    }; 

Из журналов я вижу, что мой фильтр успешно распознается приложением и принимает участие в ответах обработки (я вижу сообщения журнала из doFilter). Но фактический ответ, полученный браузером, по-прежнему содержит стандартный заголовок «WWW-Authenticate». Кажется, что кто-то переопределяет мой заголовок, я не знаю, кто это точно.

Не могли бы вы дать совет?

ответ

5

Решил проблему с помощью пользовательского EntryPoint:

protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests() 
      .antMatchers("/rest/**").authenticated() 
      .and().httpBasic().authenticationEntryPoint(new AuthenticationEntryPoint() { 
       @Override 
       public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 
        String requestedBy = request.getHeader("X-Requested-By"); 
        log.info("X-Requested-By: " + requestedBy); 
        if(requestedBy == null || requestedBy.isEmpty()) { 
         HttpServletResponse httpResponse = (HttpServletResponse) response; 
         httpResponse.addHeader("WWW-Authenticate", "Basic realm=Cascade Realm"); 
         httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); 
        } else { 
         HttpServletResponse httpResponse = (HttpServletResponse) response; 
         httpResponse.addHeader("WWW-Authenticate", "Application driven"); 
         httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); 
        } 
       } 
      }); 
} 
1

Фильтр Spring Security будет добавлен с наименьшим приоритетом, так что, вероятно, он находится выше по потоку от вас. Вы можете попробовать более низкий порядок. Обычный способ обработки 401 ответов - с AuthenticationFailureHandler, но я полагаю, я могу понять, почему вы можете сделать это таким образом, учитывая, что базовый auth уже существует.

+0

Спасибо за ответ. Я пробовал обычный способ, о котором вы упоминали, - это действительно полезно, но это не то, что я ищу. Кажется, что AuthenticationFailureHandler запускается только при неудачной попытке аутентификации (недопустимые учетные данные, отправленные пользователем в форме входа). Но то, что я ищу, - это способ прозрачной настройки некоторых заголовков ответов, прежде чем отвечать на HTTP-клиент. В исходной среде сервлетов я смог сделать это с помощью фильтров, но весной этот подход работает по-разному ... – skapral

+0

Фильтры - это фильтры. Единственная проблема, которую я предвижу, заключается в том, что вам может понадобиться замаскировать ответ, чтобы он не был зафиксирован, прежде чем ваш фильтр сможет выполнить свою задачу. Но вы сказали, что у вас уже есть такая работа, поэтому все, что вам нужно сделать, это получить ее в правильном порядке. Это довольно просто (просто измените порядок). –

0

Просто добавьте "X-Requested-With: XMLHttpRequest" в заголовке запроса (Испытано в Spring Security 4.2.2.RELEASE).

Для получения дополнительной информации HttpBasicConfigurer стоит поискать.

Ниже мой результат теста с помощью CURL:

hanxideMacBook-Pro:~ hanxi$ curl -u "13980547109:xxx" -v -d "" -H "X-Requested-With: XMLHttpRequest" http://sales.huoxingy.com/api/v1/sales/login 
* Trying 101.37.135.20... 
* TCP_NODELAY set 
* Connected to sales.huoxingy.com (101.37.135.20) port 80 (#0) 
* Server auth using Basic with user '13980547109' 
> POST /api/v1/sales/login HTTP/1.1 
> Host: sales.huoxingy.com 
> Authorization: Basic MTM5ODA1NDcxMDk6MTIzNDU2 
> User-Agent: curl/7.54.0 
> Accept: */* 
> X-Requested-With: XMLHttpRequest 
> Content-Length: 0 
> Content-Type: application/x-www-form-urlencoded 
> 
< HTTP/1.1 200 
< Server: nginx/1.12.1 
< Date: Thu, 21 Sep 2017 01:43:13 GMT 
< Content-Length: 0 
< X-Content-Type-Options: nosniff 
< X-XSS-Protection: 1 
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate 
< Pragma: no-cache 
< Expires: 0 
< X-Frame-Options: DENY 
< X-XSS-Protection: ; mode=block 
< x-auth-token: 2f595113-cdba-4394-8ca0-bcd72239bea5 
< Set-Cookie: CONTAINERID=efc390abdb189a10c55e0672b07cfe1c7d665be4db9ad40e122475e5cdff605d; path=/ 
Смежные вопросы