How can I determine what roles are required to access a URL with Spring Security?

耗尽温柔 提交于 2020-01-01 11:36:16

问题


I'm using Spring Security to secure a webapp. The URLs are secured like this:

<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>

I have a filter that needs to redirect the user to a special page under certain circumstances. However, that page requires images and CSS files in the assets directory which will unfortunately also be redirected to that special page. I don't want the filter to manually check against each URL pattern because my actual URL configuration is much longer, and I also want to allow other pages.

Is there a way to determine from the filter for a given page what roles are required? I could then choose not to redirect if ROLE_ANONYMOUS is not required.


回答1:


Assuming you're using Spring Security 3, the source of that information (which attributes/roles are configured for a particular path) is the FilterInvocationSecurityMetadataSource that is injected into the FilterSecurityInterceptor. So if you have a particular URL, then you can query the configured attributes by passing a FilterInvocation (created from the request and response) to the getAttributes() method of FilterInvocationSecurityMetadataSource.

Getting a reference to inner beans created by the namespace can be a bit tricky. Assuming you have your own bean (or beans) that you want to make the call from, you can inject it into them by adding a BeanPostProcessor to your application context, which is implemented something like this:

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;
    }   
}

Note that Spring Security automatically registers a WebInvocationPrivilegeEvaluator in the context which can be used to check whether a user has the ability to invoke a particular URL without actually invoking it. This is similar, in that it queries the SecurityMetadataSource, but not quite what you're after here.




回答2:


Don't forget that what actually happens when deciding whether to allow access is that the URL and existing authentication is passed through a series of AccessDecisionVoters, one of the default of which is the RoleVoter. This voter checks the configuration for the requested resource, and if a specific role is required, will deny the request if the existing authentication doesn't have that role.

So to the solution - you can add other voters that kick in before the role voter. Each voter must return GRANT, DENY or ABSTAIN, and processing only continues to later voters if ABSTAIN is returned. Thus you can write your own custom voter (or reuse an existing one if this would work), have it fire before the role voter, and unconditionally grant access to any requests to the resources you're referring to.

I have done something like this in a current project, where certain transient application-specific attributes can let someone access resources that ordinarily they would not be able to, and it works well as an approach.



来源:https://stackoverflow.com/questions/453925/how-can-i-determine-what-roles-are-required-to-access-a-url-with-spring-security

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!