使用 javassist 注入 Spring 安全配置代码
Injecting Spring security config code using javaassist
我有一个 spring 引导应用程序,在应用程序启动期间,我试图使用 Java 注入 Spring-安全 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: [source error] authorizeRequests() not found in org.springframework.security.config.annotation.web.HttpSecurityBuilder
它正在 class HTTPSecurityBuilder 中寻找 authorizeRequests(),但它实际上必须查看 class "HttpSecurity"。我怎样才能解决这个问题?提前致谢。
Javassist 不支持泛型,只尊重任何方法的擦除。正如您在 from the javadoc of CsrfConfigurer 中看到的那样,禁用方法是通用的,这就是为什么 Javassist 假设了错误的类型并且无法解析正确的方法。
处理此问题的唯一方法是在 Spring 安全 DSL 的任何通用步骤之后添加适当的类型转换,不幸的是,这几乎是每一步。
如果您正在寻找不受此限制的替代方案,请查看我的库 Byte Buddy,它使用编译代码而不是字符串,并且不受此限制。
我有一个 spring 引导应用程序,在应用程序启动期间,我试图使用 Java 注入 Spring-安全 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: [source error] authorizeRequests() not found in org.springframework.security.config.annotation.web.HttpSecurityBuilder
它正在 class HTTPSecurityBuilder 中寻找 authorizeRequests(),但它实际上必须查看 class "HttpSecurity"。我怎样才能解决这个问题?提前致谢。
Javassist 不支持泛型,只尊重任何方法的擦除。正如您在 from the javadoc of CsrfConfigurer 中看到的那样,禁用方法是通用的,这就是为什么 Javassist 假设了错误的类型并且无法解析正确的方法。
处理此问题的唯一方法是在 Spring 安全 DSL 的任何通用步骤之后添加适当的类型转换,不幸的是,这几乎是每一步。
如果您正在寻找不受此限制的替代方案,请查看我的库 Byte Buddy,它使用编译代码而不是字符串,并且不受此限制。