使用javaassist注入Spring安全配置代码

时间:2016-11-11 07:44:32

标签: spring-security javassist

我有一个spring boot应用程序,在应用程序启动期间,我尝试使用Javaassist注入Spring-Security Java配置。我从DB的值动态生成java配置。这是代码,

public class WarLock implements SpringApplicationRunListener {
private final SpringApplication application;

public WarLock(SpringApplication application, String[] args) throws IOException {
    this.application = application;
}

@Override
public void started() {
    try {
        System.out.println("Re-write security config called");
        rewriteSecurityConfigClass();
    } catch (NotFoundException | CannotCompileException e) {
        e.printStackTrace();
    }
}

private void rewriteSecurityConfigClass() throws NotFoundException, CannotCompileException {

    SecurityConfig config = new SecurityConfig();

    ClassPool cp = ClassPool.getDefault();
    cp.appendClassPath(new LoaderClassPath(application.getClassLoader()));
    CtClass compiledClass = cp.get(config.getClass().getName());

    CtClass[] argClasses = { cp.get(HttpSecurity.class.getName()) };

    CtMethod method = compiledClass.getDeclaredMethod("configure",argClasses);

    method.setBody("http    .csrf().disable()                   "+
            ".authorizeRequests()                               "+
            "   .antMatchers(\"/css/**\", \"/index\").permitAll()   "+
            "   .antMatchers(\"/user/**\").hasAuthority(\"USER\")   "+
            "   .antMatchers(\"/tryadmin\").hasAuthority(\"ADMIN\") "+
            "   .antMatchers(\"/try\").hasAuthority(\"USER\")       "+
            "   .and()                                          "+
            ".authenticationProvider(authenticationProvider())  "+
            "   .exceptionHandling()                            "+
            "   .authenticationEntryPoint(entryPoint)           "+
            "   .and()                                          "+
            ".formLogin()                                       "+
            "   .usernameParameter(\"username\")                    "+
            "   .passwordParameter(\"password\")                    "+
            "   .successHandler(loginSuccessHandler)            "+
            "   .failureHandler(loginFailureHandler)            "+
            "   .and()                                          "+
            ".logout()                                          "+
            "    .permitAll()                                   "+
            "    .logoutRequestMatcher(new AntPathRequestMatcher(\"/login\", \"DELETE\"))   "+
            "    .logoutSuccessHandler(logoutSuccessHandler)                                "+
            "    .deleteCookies(\"JSESSIONID\")                                         "+
            "    .invalidateHttpSession(true)                                           "+
            "    .and()                                                                 "+
            ".sessionManagement()                                                       "+
            "   .enableSessionUrlRewriting(true)                                        "+
            "   .maximumSessions(1);                                                        ");         

    compiledClass.toClass();

但启动时代码失败,

  

javassist.CannotCompileException:在org.springframework.security.config.annotation.web.HttpSecurityBuilder中找不到[source error] authorizeRequests()

它正在类HTTPSecurityBuilder中寻找authorizeRequests(),但它实际上必须查看类“HttpSecurity”。我怎样才能解决这个问题?提前谢谢。

1 个答案:

答案 0 :(得分:1)

Javassist不支持泛型类型,但只考虑任何方法的擦除。正如您在from the javadoc of CsrfConfigurer中看到的那样,disable方法是通用的,这就是为什么Javassist假定类型错误并且无法解析正确的方法。

处理此问题的唯一方法是在Spring Security DSL的任何通用步骤之后添加适当的类型转换,不幸的是,这几乎是每一步。

如果您正在寻找不受此限制的替代方案,请查看我的库Byte Buddy,它使用已编译的代码而不是字符串,并且不受此限制。