检查经过身份验证的用户

时间:2017-05-26 14:11:47

标签: java spring-boot spring-security

我已经使用spring-boot-1.5.3设置了spring-security-4.2.2个应用程序,并根据权限配置了受限制的路径。这些限制与此类似:

@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的用户能够访问我的整个网络应用,但/accounts/**/roles/**路径除外。如果我在没有适当权限的情况下尝试访问这些页面,那么这种配置工作正常并且我得到预期的错误(403)。

对于具有USER权限的用户,我想隐藏一些网址,以便他们不会发出这些请求并导致403错误。 如何检查是否允许用户访问网址

到目前为止,我已尝试注入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

2 个答案:

答案 0 :(得分:0)

而是使用方法来检查用户是否具有权限。

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

答案 1 :(得分:0)

我通过访问Spring安全性的内部过滤器来提出这个问题的解决方案(看起来真的是hackish,虽然它有效)。

首先,我创建了一个帮助程序类来检查URL是否可访问:

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;