2016-11-11 3 views
1

У меня есть приложение загрузки весны, где во время запуска приложения я пытаюсь внедрить конфигурацию Java Spring-Security с помощью Javaassist. Я генерирую java-конфигурацию динамически из значений из БД. Вот код,Код конфигурации безопасности для инъекций Spring с использованием javaassist

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: [Ошибка источника] authorizeRequests() не найден в org.springframework.security.config.annotation. web.HttpSecurityBuilder

он ищет authorizeRequests() внутри класса HTTPSecurityBuilder, но на самом деле должны смотреть в класс «HttpSecurity». Как я могу это исправить? Заранее спасибо.

ответ

1

Javassist не поддерживает общие типы, но только уважает стирание любого метода. Как вы можете видеть в from the javadoc of CsrfConfigurer, метод disable является общим, поэтому Javassist принимает неправильный тип и не может решить правильный метод.

Единственный способ справиться с этим заключается в добавлении соответствующего типа литья после любого общего шага Spring Security DSL, который, к сожалению, почти на каждом шагу.

Если вы ищете альтернативу, которая не страдает этим ограничением, посмотрите на мою библиотеку Byte Buddy, которая работает с скомпилированным кодом, а не с строками, и не страдает этим ограничением.

+0

Спасибо за ваш ответ. Просто чтобы понять, как я могу добавить кастинг в эту цепочку методов? – arunan

+0

Как и в коде Java. Поместите класс HttpSecurity в фигурные скобки и поместите его в область, к которой вы хотите вызвать метод. –