Spring、安全、启动、WebSecurityConfigurerAdapter - 通过在数据库中查找动态拦截 URL

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

我是 Spring、Spring 安全和引导的新手 - 尝试创建一个 Web 应用程序,我必须在数据库中查找用户是否有权访问所请求的 URL 或不。我已经设法使身份验证工作(即带有 loadUserByUsername 的 UserDetailService)。在数据库中,我有一个 table 用于用户、组、角色,最后一个用于 URLs 包含 URLs 和配置属性(通常等于角色)。

所以我有这个工作配置(顺便说一下,我正在尝试配置 Java 中的所有内容 - 不使用 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();

现在我正在尝试将上面所有的 antMatchers 替换为:

        .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();

MyFilterSecurityMetadataSource 如下(我还没有进行实际查找 - 我很难找到这个过滤器):

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

也许我需要配置一个 FilterSecurityInterceptor 而不是 MyFilterSecurityMetadataSource 并将其传递给 FilterSecurityInterceptor,我不知道。但后来我必须使用 decisionManagers roleVotes bla。布拉。我不明白。很难找到关于这个特定主题的工作样本。抱歉,我的编程技术很烂:)

您在错误的对象上获得了 post 处理器。请用以下

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