8

Is there a way, using Spring Security (v 3.1.x), to programmatically get authorization rules for a certain URL?

I mean... suppose I set:

<security:intercept-url pattern="/**" access="isAuthenticated()" />

in my configuration.

In the controller handling /internal/** paths I'd like to know if I need authentication to access a certain path. A method like this:

boolean isAuthenticationRequired(String ulr);

could be useful.

Can I get this information via SecurityContextHolder?

UPDATE Searching around it seems that the key could be SecurityMetadataSource...

davioooh
  • 23,742
  • 39
  • 159
  • 250
  • This is not an answer to your question but tip that will probably help you. Try to cause exception during authentication. Analyze the stack trace and find where the code that performs the authentication. Look around, you will see the API you need. Good luck. – AlexR Jun 23 '14 at 15:07
  • No problem. Good luck with this. Please post "right" self answer when you find the solution. – AlexR Jun 24 '14 at 07:12
  • @AlexR I hope to find it... :D – davioooh Jun 24 '14 at 07:13

1 Answers1

1

If you're using schema-based configuration I think this is the only (and ugly) way to get to the SecurityMetadataSource and the rules:

@Autowired
private ApplicationContext applicationContext;

public void someMethod(){
    FilterSecurityInterceptor fsi = applicationContext.getBean(org.springframework.security.web.access.intercept.FilterSecurityInterceptor.class);
    FilterInvocationSecurityMetadataSource sms = fsi.getSecurityMetadataSource();

    try {
        Field field = sms.getClass().getDeclaredField("requestMap");
        field.setAccessible(true);
        Map<RequestMatcher, Collection<ConfigAttribute>> requestMap = (Map<RequestMatcher, Collection<ConfigAttribute>>)field.get(sms);
        Set<Entry<RequestMatcher, Collection<ConfigAttribute>>> entrySet = requestMap.entrySet();
        for (Entry<RequestMatcher, Collection<ConfigAttribute>> entry : entrySet) {
            AntPathRequestMatcher path = (AntPathRequestMatcher)entry.getKey();                     
            System.out.println(path.getPattern());
                            //prints sthg like /action/index
            Collection<ConfigAttribute> roles = entry.getValue();
            System.out.println(roles);
                            //[ROLE_USER,ROLE_ADMIN]
        }
    } catch (Exception e) {
        //TODO
        e.printStackTrace();
    }
}

Using this you can easily program a utility service to check a URL.

The alternative is cleaner but in the end more verbose: if you're not using schema-based configuration, you can access more easily the bean containing the mapping (interceptedUrls):

<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
    <property name="securityMetadataSource" ref="interceptedUrls"/>
</bean>


<sec:filter-invocation-definition-source id="interceptedUrls">       
    <sec:intercept-url pattern="/action/login" access="ROLE_ANONYMOUS"/>
    <sec:intercept-url pattern="/action/passwordReset" access="ROLE_ANONYMOUS"/>        

    <sec:intercept-url pattern="/action/index" access="ROLE_ADMIN"/>
    ...

Hope this helps!

codependent
  • 23,193
  • 31
  • 166
  • 308