2017-05-26 83 views
1

訪問我設置一個spring-boot-1.5.3應用與spring-security-4.2.2和基於當局配置限制的路徑。這些限制類似於此:檢查URL是通過身份驗證的用戶

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(securedEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests() 
       .antMatchers("/accounts/**", "/roles/**") 
        .hasAuthority(ADMINISTRATOR) 
        .and() 
       .antMatchers("/**") 
        .hasAuthority(USER) 
        .and() 
      .formLogin() 
       .loginPage("/login") 
       .permitAll() 
       .and() 
      .logout() 
       .permitAll() 
       .and() 
      .csrf() 
       .disable(); 
    } 
} 

總之 - 我希望用戶有權力USER到能夠訪問我的整個Web應用程序,除了/accounts/**/roles/**路徑。此配置工作正常,如果我嘗試訪問這些頁面而沒有相應的權限,則會收到預期的錯誤(403)。

對於具有USER權限的用戶,我想隱藏一些URL,以便它們不發出這些請求並獲得403錯誤。 我如何檢查是否允許用戶訪問的URL

到目前爲止,我已經嘗試注入WebInvocationPrivilegeEvaluator並調用它的isAllowed方法,雖然這似乎並不奏效。例如:

// Helper class that returns authentication instance. 
Authentication auth = AuthUtils.getAuthentication(); 

// Don't have permission to access /users, expect to get false result. 
boolean res = webInvocationPrivilegeEvaluator.isAllowed("/users", auth); 

assert res == false; // fails 

回答

0

我已經想出了一個通過訪問彈簧安全性的內部過濾器(看起來真的很危險,雖然它工作)的這個問題的解決方案。

首先我創建了一個輔助類來檢查,如果網址可以訪問:

public final class UrlAuthorization { 
    private static final Logger LOG = LoggerFactory.getLogger(UrlAuthorization.class); 

    private final FilterInvocationSecurityMetadataSource securityMetadataSource; 
    private final AccessDecisionManager accessDecisionManager; 

    public UrlAuthorization(FilterInvocationSecurityMetadataSource securityMetadataSource, 
          AccessDecisionManager accessDecisionManager) { 

     this.securityMetadataSource = securityMetadataSource; 
     this.accessDecisionManager = accessDecisionManager; 
    } 

    public boolean isAccessible(String url) { 
     Authentication authentication = AuthUtils.getAuthentication(); 

     FilterInvocation invocation = new FilterInvocation(null, url, HttpMethod.GET.name()); 
     Collection<ConfigAttribute> attributes = securityMetadataSource 
       .getAttributes(invocation); 

     try { 
      this.accessDecisionManager.decide(authentication, invocation, attributes); 

     } catch (AccessDeniedException e) { 
      LOG.trace("Not allowed to access URL: {}", url, e); 
      return false; 
     } 
     return true; 
    } 
} 

然後我說配置該類創建一個Bean

@Configuration 
public class UrlAuthorizationConfiguration { 

    @Bean 
    public UrlAuthorization urlAuthorization(List<Filter> filters) { 
     FilterSecurityInterceptor interceptor = getInterceptor(filters) 
       .orElseThrow(() -> new BeanCreationException("Could not get security interceptor")); 

     return new UrlAuthorization(
       interceptor.getSecurityMetadataSource(), 
       interceptor.getAccessDecisionManager() 
     ); 
    } 

    private Optional<FilterSecurityInterceptor> getInterceptor(List<Filter> filters) { 
     for (Filter filter : filters) { 
      if (filter instanceof FilterChainProxy) { 
       for (SecurityFilterChain chain : ((FilterChainProxy) filter).getFilterChains()) { 
        for (Filter securityFilter : chain.getFilters()) { 
         if (securityFilter instanceof FilterSecurityInterceptor) { 
          return Optional.of(((FilterSecurityInterceptor) securityFilter)); 
         } 
        } 
       } 
      } 
     } 
     return Optional.empty(); 
    } 
} 

最後,我可以用它像這樣:

assert urlAuthorization.isAccessible("/accounts") == false; 
assert urlAuthorization.isAccessible("/") == true; 
+0

可能的好主意,但不適用於@PreAuthorize。我所得到的FilterSecurityInterceptor確實只返回securityMetaDataSource和「authenticated」過濾器,而有問題的URL有@PreAuthorize(「hasRole('ADMIN')」)註釋。看起來我必須得到不同的過濾器,才能提供PreAuthorize中列出的所有條件 – tequilacat

0

而是使用方法來檢查用戶是否有權限。

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role) 
+0

如果我使用這種方法,我將不得不在每個URL(che ck如果用戶在顯示特定的URL之前有角色)。此外,如果我使用這種方法,則必須將每個URL與特定角色相關聯,而我已通過授權在「WebSecurityConfig」中完成此操作。另外請記住,我沒有使用角色,我正在使用權限。所以這種方法對我不起作用。 – Edd

+1

理想情況下,我想是這樣'WebInvocationPrivilegeEvaluator.isAllowed(URL)'。它應該工作,我猜,儘管它似乎總是返回「真」,無論我提供給這個方法的參數。 – Edd

相關問題