我已经使用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
答案 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;