如何将参数从自定义注释传递到库中的WebSecurityConfigurer



嗨,我们正在构建自定义弹簧安全库

我们需要通过主项目中存在的@EnableMySpringSecurity(excludePaths = {"/v1","/v2"})将{"/v1","/v2"}路径传递给库网络安全,这样我们就可以忽略安全中的那些端点

@EnableMySpringSecurity(excludePaths = {"/v1","/v2"})
@EnableWebMvc
public class WebAppConfiguration extends BaseWebAppConfiguration {

来自自定义JAR 的网络安全配置

@EnableWebSecurity(debug = true)
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web){
web.ignoring().antMatchers(excludePaths );

如何将从@EnableMYSpringSecurity传递到webSecurity web.ignoring.antMatchers 的值

我们的注释配置

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EnableMySpringSecurity {
String[] excludePaths() default {};
}

我尝试过ApplicationStartupListener,但问题是,它是在网络安全配置后初始化的

public class ApplicationStartupListener implements
ApplicationListener<ContextRefreshedEvent> {
private ApplicationContext context;
private EnableMySSAnnotationProcessor processor;
public ApplicationStartupListener(ApplicationContext context,
EnableMySSAnnotationProcessor processor) {
this.context = context;
this.processor = processor;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
Optional<EnableMySpringSecurity> annotation =
context.getBeansWithAnnotation(EnableMySpringSecurity.class).keySet().stream()
.map(key -> context.findAnnotationOnBean(key, EnableMySpringSecurity.class))
.findFirst();
annotation.ifPresent(enableMySpringSecurity-> processor.process(enableMySpringSecurity));
}
}

实现这一点的一种方法是使用@Import注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyWebSecurityConfiguration.class)
@EnableWebSecurity
public @interface EnableMyWebSecurity {
String[] paths() default [];
}

然后ImportAware接口:

@Configuration
public class MyWebSecurityConfiguration implements ImportAware {
private String[] paths;
@Bean
WebSecurityCustomizer paths() {
return (web) -> web.ignoring().antMatchers(paths);
}
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
EnableMyWebSecurity annotation = importMetadata
.getAnnotations().get(EnableMyWebSecurity.class).synthesize();
this.paths = annotations.paths();
}
}

顺便注意,当您排除路径时,SpringSecurity不能将安全头作为响应的一部分添加。如果您希望这些端点由Spring Security保护,但是公共的,那么请考虑:

@Configuration
public class MyWebSecurityConfiguration implements ImportAware {
private String[] paths;
@Bean
@Order(1)
SecurityFilterChain paths(HttpSecurity http) {
http
.requestMatchers((requests) -> requests.antMatchers(paths))
.authorizeRequests((authorize) -> authorize
.anyRequest().permitAll()
);
return http.build();
}
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
EnableMyWebSecurity annotation = importMetadata
.getAnnotations().get(EnableMyWebSecurity.class).synthesize();
this.paths = annotations.paths();
}
}

第二种方法的好处是SpringSecurity不需要身份验证,但会添加安全的响应头。

jzheaux提供的解决方案适用于

还有一个解决方案,就是使用应用程序上下文getBeansWithAnnotation

@EnableWebSecurity(debug = true)
@Configuration
@Order(2147483640)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private ApplicationContext appContext;
@Override
public void configure(WebSecurity web){
Map<String,Object> beanMap = this.appContext.getBeansWithAnnotation(EnableMYSpringSecurity.class);
if(!beanMap.isEmpty()){
EnableMYSpringSecurityanno = (EnableMYSpringSecurity) this.appContext.findAnnotationOnBean(beanMap.keySet()
.iterator()
.next(),EnableMYSpringSecurity.class);
String[] permitPaths = anno.excludePaths();
Arrays.stream(permitPaths).forEach(System.out::println);
}

相关内容

  • 没有找到相关文章

最新更新