2013-11-04 61 views
0

我正在嘗試使用角色的Spring Security的Java配置,以便只授予對已認證用戶的訪問權限。登錄過程正在工作,但是當我使用應該訪問受限的角色登錄時,我仍然能夠訪問應該受保護的路由。這裏是我使用HTTP配置WebSecurityConfigurerAdapter類:SpringSecurity - 登錄後不阻止訪問

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

@Autowired 
DataConfig dataConfig; 

private final String QUERY_USERS = "select email, password, enabled from Account where email=?"; 
private final String QUERY_AUTHORITIES = "select a.email, au.authority from Account a, Authority au where a.email = au.email and a.email =? "; 

@Override 
protected void configure(HttpSecurity http) throws Exception { 

    http 
    .authorizeUrls() 
    .antMatchers("/public/login.jsp").permitAll() 
    .antMatchers("/public/home.jsp").permitAll() 
    .antMatchers("/public/**").permitAll() 

    .antMatchers("/secured/**").fullyAuthenticated() 
    .antMatchers("/resources/clients/**").fullyAuthenticated() 
    .antMatchers("/secured/user/**").hasRole("USER") 
    .antMatchers("/secured/admin/**").hasRole("ADMIN") 

    .and() 
    .formLogin() 
     .loginPage("/login") 
     .loginProcessingUrl("/j_spring_security_check") 
     .failureUrl("/loginfailed") 
     .usernameParameter("j_username") 
     .passwordParameter("j_password") 

    .and() 
    .logout() 
     .logoutUrl("/j_spring_security_logout")  // The URL that triggers logout to occur on HTTP POST 
     .logoutSuccessUrl("/logout") // The URL to redirect to after logout has occurred 
     .invalidateHttpSession(true); // Clear the session 
} 

@Override 
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception { 

    // Use the database 
    auth 
    .jdbcAuthentication() 
     .passwordEncoder(new org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder()) 
     .dataSource(dataConfig.dataSource()) 

     .withDefaultSchema() 
     .usersByUsernameQuery(QUERY_USERS) 
     .authoritiesByUsernameQuery(QUERY_AUTHORITIES);  
    } 
} 

,這裏是我的WebApplicationInitializer類,我註冊了安全過濾器鏈:

public class DatabaseWebApplicationInitializer implements WebApplicationInitializer { 

private static final Class<?>[] configurationClasses = new Class<?>[] { 
       AppConfig.class, DbConfig.class, SecurityConfig.class}; 

private static final String DISPATCHER_SERVLET_NAME = "dispatcher"; 

@Override 
public void onStartup(ServletContext servletContext) throws ServletException { 
    registerListener(servletContext);   
    registerDispatcherServlet(servletContext); 

    registerSpringSecurityFilterChain(servletContext); 
} 

private void registerDispatcherServlet(ServletContext servletContext) { 

    // creates an application context for direct registration of 
    // @Configuration and other @Component-annotated classes 
    AnnotationConfigWebApplicationContext dispatcherContext = createContext(AppConfig.class); 

    ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, 
      new DispatcherServlet(dispatcherContext)); 
    dispatcher.setLoadOnStartup(1); 
    dispatcher.addMapping("/"); 
} 

private void registerListener(ServletContext servletContext) { 
    AnnotationConfigWebApplicationContext rootContext = createContext(configurationClasses); 
    servletContext.addListener(new ContextLoaderListener(rootContext)); 
    servletContext.addListener(new RequestContextListener()); 
} 


private void registerSpringSecurityFilterChain(ServletContext servletContext) { 
    FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(
      BeanIds.SPRING_SECURITY_FILTER_CHAIN, new DelegatingFilterProxy()); 
    springSecurityFilterChain.addMappingForUrlPatterns(null, false, "/*"); 
} 

private AnnotationConfigWebApplicationContext createContext(final Class<?>... annotatedClasses) { 
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); 

    // set the active profile 
    context.getEnvironment().setActiveProfiles("dev"); 

    context.register(annotatedClasses); 
    return context; 
} 

}

如果我登錄使用的憑證,只有具有USER(不是ADMIN)的角色,但我仍然可以訪問/secured/admin/**的路由,但我認爲這應該僅限於具有ADMIN角色的路由。如果您有任何建議,請告訴我,或者可以指出我的一個很好的例子。

回答

3

我有理由相信這是與您的.antMatchers()聲明的順序有關。

您目前在.antMatchers("/secured/admin/**").hasRole("ADMIN")之前有.antMatchers("/secured/**").fullyAuthenticated()。 Spring Security可能與這個第一匹配器匹配,並應用fullyAuthenticated()檢查,這意味着如果您只有角色USER,則授予該授權。

我建議重新排序的東西,這樣你.antMatchers()聲明是這樣的:

.antMatchers("/public/login.jsp").permitAll() 
.antMatchers("/public/home.jsp").permitAll() 
.antMatchers("/public/**").permitAll() 
.antMatchers("/resources/clients/**").fullyAuthenticated() 
.antMatchers("/secured/user/**").hasRole("USER") 
.antMatchers("/secured/admin/**").hasRole("ADMIN") 
.antMatchers("/secured/**").fullyAuthenticated() 

在這種情況下,Spring將回落至之前匹配特定訪問/secured/admin/**/secured/user/**資源較早的規則/secured/**聲明。

+0

感謝您的及時回覆。建議我已經重新訂購了antMatchers(),但沒有運氣。 –

+0

這個問題可能是由Spring Security版本引起的嗎?我目前使用3.2.0.M2。我也嘗試過使用3.2.0.RC1 –

+0

如果可以將日誌級別更改爲DEBUG。你會看到你在那裏尋找的信息。 – ampofila