我正在使用Spring Security来保护webapp。 URL的安全性如下:
<security:http entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/assets/**/*" access="ROLE_ANONYMOUS" />
...
<security:intercept-url pattern="/**" access="ROLE_USER" />
<security:anonymous granted-authority="ROLE_ANONYMOUS" />
</security:http>
我有一个过滤器,在某些情况下需要将用户重定向到特殊页面。但是,该页面需要资产目录中的图像和CSS文件,遗憾的是,这些文件也会被重定向到该特殊页面。我不希望过滤器手动检查每个URL模式,因为我的实际URL配置要长得多,而且我还想允许其他页面。
有没有办法从过滤器中确定给定页面需要哪些角色?如果不需要ROLE_ANONYMOUS,我可以选择不重定向。
答案 0 :(得分:3)
假设您正在使用Spring Security 3,该信息的来源(为特定路径配置了哪些属性/角色)是注入FilterSecurityInterceptor的FilterInvocationSecurityMetadataSource。因此,如果您有特定的URL,则可以通过将FilterInvocation(从请求和响应创建)传递给FilterInvocationSecurityMetadataSource的getAttributes()方法来查询已配置的属性。
获取对命名空间创建的内部bean的引用可能有点棘手。假设您有自己想要进行调用的bean(或bean),可以通过向应用程序上下文添加BeanPostProcessor将其注入到它们中,实现如下:
public class FilterSecurityMDSExtractor implements BeanPostProcessor, BeanFactoryAware {
private ConfigurableListableBeanFactory bf;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof FilterInvocationSecurityMetadataSource) {
// Get your own bean from the BeanFactory here and inject the SecurityMetadataSource into it
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.bf = (ConfigurableListableBeanFactory)beanFactory;
}
}
请注意,Spring Security会自动在上下文中注册WebInvocationPrivilegeEvaluator,可用于检查用户是否能够在不实际调用的情况下调用特定URL。这是类似的,因为它查询SecurityMetadataSource,但不完全是你在这里。
答案 1 :(得分:2)
不要忘记在决定是否允许访问时实际发生的事情是URL和现有身份验证是通过一系列AccessDecisionVoter传递的,其中一个默认值是RoleVoter 。此选民检查所请求资源的配置,如果需要特定角色,则在现有身份验证没有该角色时拒绝该请求。
因此,对于解决方案 - 您可以添加在角色选民之前启动的其他选民。每个选民必须返回GRANT,DENY或ABSTAIN,并且如果返回ABSTAIN,则仅对后来的选民继续处理。因此,您可以编写自己的自定义选民(或者如果可行则重复使用现有选民),在角色选民之前启动它,并无条件地授予对您所指的资源的任何请求的访问权。
我在当前的项目中做过类似的事情,某些瞬态特定于应用程序的属性可以让某些人访问通常他们无法访问的资源,并且它可以很好地作为一种方法。