Spring, security, boot, WebSecurityConfigurerAdapter - intercepting URL's dynamically via lookup in DB

时间:2015-05-24 22:17:32

标签: spring-security spring-java-config

I'm new to Spring, SpringSecurity and Boot - trying to create a webapplication where I have to lookup in a database whether a user has access to a requested URL or not. I've managed to make the authentication work (i.e UserDetailService with loadUserByUsername). In the database I have a table for Users, Groups, Roles and a last one for URLs containing the URLs and Config Attributes (typically equal to the Roles).

So I have this working configuration (by the way, I'm trying to configure everything in Java - not using XML):

@Resource(name="authService")
private UserDetailsService userDetailsService;
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider());
}
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
@Bean
AuthenticationProvider customAuthenticationProvider() {
    DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
    authProvider.setUserDetailsService(userDetailsService);
    authProvider.setPasswordEncoder(passwordEncoder());
    return authProvider;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .formLogin()
        .loginPage("/login")
        .loginProcessingUrl("/login")
        .usernameParameter("username")
        .passwordParameter("password")
        .defaultSuccessUrl("/table/list").permitAll()
    .and()
    .logout()
        .logoutUrl("/logout").permitAll()
    .and()
    .authorizeRequests()
    .antMatchers(
        "/home",
        "/images/**",
        "/bootstrap/**",
        "/jquery-ui/**",
        "/jquery-2.1.3.min.js",
        "/error"
    ).permitAll()
    .antMatchers("/user/list").permitAll()
    .antMatchers("/user/create/**").permitAll()
    .antMatchers("/user/created/**").permitAll()
    .antMatchers("/user/update/**").permitAll()
    .antMatchers("/user/updated/**").permitAll()
    .antMatchers("/table/list").hasRole("ADMIN")
    .antMatchers("/table/create").hasRole("USER")
    .antMatchers("/table/created").hasRole("USER")
    .anyRequest().denyAll();

Now I'm trying to replace all above antMatchers with:

        .anyRequest().authenticated()
    .withObjectPostProcessor(new ObjectPostProcessor<MyFilterSecurityMetadataSource>() {
        @Override
        public <O extends MyFilterSecurityMetadataSource> O postProcess(O object) {
            object.getAttributes(object);
            FilterInvocationSecurityMetadataSource metadataSource = new MyFilterSecurityMetadataSource();
            if (object instanceof FilterInvocationSecurityMetadataSource) {
                return (O) metadataSource.getAttributes(object);
            }
            return null;
        }
    }).anyRequest().denyAll();

And MyFilterSecurityMetadataSource is as follows (I'm not doing an actual lookup yet - I have a hard time getting to this filter):

public class MyFilterSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

public List<ConfigAttribute> getAttributes(Object object) {
    FilterInvocation fi = (FilterInvocation) object;
    String fullRequestUrl = fi.getFullRequestUrl();
    String requestUrl = fi.getRequestUrl();
    String httpMethod = fi.getRequest().getMethod();
    String contextPath = fi.getRequest().getContextPath();
    System.out.println("Full request URL: " + fullRequestUrl);
    System.out.println("Request URL: " + requestUrl);
    System.out.println("HTTP Method: " + httpMethod);
    System.out.println("Context path: " + contextPath);
    List<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>(0);
    // Lookup your database (or other source) using this information and populate the
    // list of attributes

    return configAttributes;
}

public Collection<ConfigAttribute> getAllConfigAttributes() {
    return null;
}

public boolean supports(Class<?> clazz) {
    return FilterInvocation.class.isAssignableFrom(clazz);
}
}

Maybe I need to configure a FilterSecurityInterceptor instead of MyFilterSecurityMetadataSource and pass this to the FilterSecurityInterceptor, I don't know. But then I have to use decisionManagers roleVotes bla. bla. I don't get it. It's quite hard to find a working sample regarding this specific subject. Sorry, my programming skills suck :)

1 个答案:

答案 0 :(得分:2)

你有错误对象的后处理器。请使用以下

重写后处理器
.anyRequest().authenticated().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    public <O extends FilterSecurityInterceptor> O postProcess(
                            O fsi) {
                        FilterInvocationSecurityMetadataSource newSource = new MyFilterSecurityMetadataSource();
                        fsi.setSecurityMetadataSource(newSource);
                        return fsi;
                    }
                })