2014-10-05 131 views
4

美好的一天。春季开机+春季安全:如何取消基本身份验证表格

我在Spring引导自动配置的应用程序中使用了Spring安全性。我的目标是设置基本身份验证,以便标准浏览器的基本身份验证表单在401上不显示。从Google发现要实现它,我需要将默认的“WWW-Authenticate”标题更改为不同于“基本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

通过使用自定义入口点问题解决了:在请求头(Spring Security的4.2.2.RELEASE测试): “XMLHttpRequest的X-要求,以”

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,但我想我可以看到为什么你可以这样做,因为基本认证已经存在。

+0

谢谢你的答复。我已经尝试了你提到的传统方式 - 确实很有用,但它不是我正在寻找的。看起来AuthenticationFailureHandler只是在错误的身份验证尝试(用户在登录表单中提交的无效凭证)时触发的。但是我正在寻找的是在答复HTTP客户端之前透明地自定义某些响应头的方法。在原始servlet环境中,我可以通过过滤器来实现,但在Spring中,这种方法似乎工作方式不同...... – skapral 2014-10-07 13:09:28

+0

过滤器是过滤器。我预见到的唯一问题是,您可能需要屏蔽响应,以防止它在您的过滤器有机会完成任务之前提交。但是你说你已经有了这个工作,所以你应该做的就是按照正确的顺序进行。这很简单(只需更改订单)。 – 2014-10-07 14:28:21

0

只需添加。

有关详细信息,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=/