2017-05-26 57 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

相关问题