2016-11-25 14 views
0

UN /安全衛生的相關信息我已經使用CAS WebSecurity以確保所有進入非認證的請求被重定向到一個共同的登錄頁面春季啓動應用程序。旁路CAS擺脫春季啓動應用

@Configuration 
@EnableWebSecurity 
public class CASWebSecurityConfig extends WebSecurityConfigurerAdapter { 

我想通過執行器公開健康端點,並添加相關依賴項。我想跳過這要通過監視工具可以使用這些/健康URL的CAS檢驗,所以在配置方法,我已經加入:

http.authorizeRequests().antMatchers("/health/**").permitAll(); 

這工作,但現在我想進一步調整它:

  • 詳細的健康狀況(即「全部內容」按照該文檔)應只能訪問一些特定的監控用戶,爲此,在屬性文件中提供的憑據。
  • 如果未提供認證,則應返回「僅限狀態」。

http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html#production-ready-health-access-restrictions,我已經配置的屬性如下,以便它應該工作:

management.security.enabled: true 
endpoints.health.sensitive: false 

但我有我如何配置憑據的問題......下面http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html#production-ready-sensitive-endpoints,我加在我的配置文件:

security.user.name: admin 
security.user.password: secret 

但它不工作 - 當我不把屬性,我沒有看到日誌生成的密碼。

所以我試圖把一些自定義的屬性,如

healthcheck.username: healthCheckMonitoring 
healthcheck.password: healthPassword 

,並注入到這些我的安全配置,使configureGlobal方法變爲:

@Autowired 
public void configureGlobal(AuthenticationManagerBuilder auth, 
          CasAuthenticationProvider authenticationProvider) throws Exception { 

    auth.inMemoryAuthentication().withUser(healthcheckUsername).password(healthcheckPassword).roles("ADMIN"); 
    auth.authenticationProvider(authenticationProvider); 
} 

,並在配置方法,我改變URL模式的配置爲:

http.authorizeRequests() 
     .antMatchers("/health/**").hasAnyRole("ADMIN") 
     .and().httpBasic() 
     .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
     .and().csrf().disable(); 

使用該配置,我滿了內容,但在邏輯上,當我沒有通過身份驗證時,我沒有得到任何狀態(UP或DOWN),因爲請求甚至沒有到達端點:它被攔截並被安全配置拒絕。

我該如何調整我的Spring Security配置,使其正常工作?我覺得我應該以某種方式鏈接配置,CAS配置首先允許請求通過純粹基於URL的方式完成,這樣,如果提供了憑據,請求就會接受第二個配置,該配置將執行基本的http身份驗證,或者讓請求未經身份驗證,否則請求端點,以便我得到「只有狀態」的結果..但同時,我認爲Spring Boot可以正確管理此配置,如果我正確配置它..

謝謝!

回答

0

解決方案也不是很大,但到目前爲止,這對我來說是什麼在起作用:

在我的配置(僅相關的代碼)

@Configuration 
@EnableWebSecurity 
public class CASWebSecurityConfig extends WebSecurityConfigurerAdapter { 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    //disable HTTP Session management 
    http 
     .securityContext() 
     .securityContextRepository(new NullSecurityContextRepository()) 
     .and() 
     .sessionManagement().disable(); 

    http.requestCache().requestCache(new NullRequestCache()); 

    //no security checks for health checks 
    http.authorizeRequests().antMatchers("/health/**").permitAll(); 

    http.csrf().disable(); 

    http 
     .exceptionHandling() 
     .authenticationEntryPoint(authenticationEntryPoint()); 

    http // login configuration 
     .addFilter(authenticationFilter()) 
     .authorizeRequests().anyRequest().authenticated(); 
} 
} 

然後我添加了一個特定的過濾器:

@Component 
public class HealthcheckSimpleStatusFilter extends GenericFilterBean { 

private final String AUTHORIZATION_HEADER_NAME="Authorization"; 

private final String URL_PATH = "/health"; 

@Value("${healthcheck.username}") 
private String username; 

@Value("${healthcheck.password}") 
private String password; 

private String healthcheckRole="ADMIN"; 

@Override 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
    throws IOException, ServletException { 
    HttpServletRequest httpRequest = this.getAsHttpRequest(request); 

    //doing it only for /health endpoint. 
    if(URL_PATH.equals(httpRequest.getServletPath())) { 

     String authHeader = httpRequest.getHeader(AUTHORIZATION_HEADER_NAME); 

     if (authHeader != null && authHeader.startsWith("Basic ")) { 
      String[] tokens = extractAndDecodeHeader(authHeader); 
      if (tokens != null && tokens.length == 2 && username.equals(tokens[0]) && password.equals(tokens[1])) { 
       createUserContext(username, password, healthcheckRole, httpRequest); 
      } else { 
       throw new BadCredentialsException("Invalid credentials"); 
      } 
     } 
    } 
    chain.doFilter(request, response); 
} 

/** 
* setting the authenticated user in Spring context so that {@link HealthMvcEndpoint} knows later on that this is an authorized user 
* @param username 
* @param password 
* @param role 
* @param httpRequest 
*/ 
private void createUserContext(String username, String password, String role,HttpServletRequest httpRequest) { 
    List<GrantedAuthority> authoritiesForAnonymous = new ArrayList<>(); 
    authoritiesForAnonymous.add(new SimpleGrantedAuthority("ROLE_" + role)); 
    UserDetails userDetails = new User(username, password, authoritiesForAnonymous); 
    UsernamePasswordAuthenticationToken authentication = 
     new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 
    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest)); 
    SecurityContextHolder.getContext().setAuthentication(authentication); 
} 

private HttpServletRequest getAsHttpRequest(ServletRequest request) throws ServletException { 
    if (!(request instanceof HttpServletRequest)) { 
     throw new ServletException("Expecting an HTTP request"); 
    } 
    return (HttpServletRequest) request; 
} 

private String[] extractAndDecodeHeader(String header) throws IOException { 
    byte[] base64Token = header.substring(6).getBytes("UTF-8"); 

    byte[] decoded; 
    try { 
     decoded = Base64.decode(base64Token); 
    } catch (IllegalArgumentException var7) { 
     throw new BadCredentialsException("Failed to decode basic authentication token",var7); 
    } 

    String token = new String(decoded, "UTF-8"); 
    int delim = token.indexOf(":"); 
    if(delim == -1) { 
     throw new BadCredentialsException("Invalid basic authentication token"); 
    } else { 
     return new String[]{token.substring(0, delim), token.substring(delim + 1)}; 
    } 
} 

}