Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically check if a certain URL needs authentication with Spring Security?

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

like image 577
davioooh Avatar asked Jun 23 '14 14:06

davioooh


1 Answers

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!

like image 156
codependent Avatar answered Oct 20 '22 05:10

codependent