如何将参数从自定义注解传递到库中的WebSecurity配置器

yh2wf1be  于 2021-10-10  发布在  Java
关注(0)|答案(2)|浏览(264)

大家好,我们正在构建定制的spring安全库
我们需要通过{/v1“,“/v2”}路径 @EnableMySpringSecurity(excludePaths = {"/v1","/v2"}) 它存在于库websecurity的主项目中,因此我们可以从安全性Angular 忽略这些端点

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

自定义jar中的web安全性配置

@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,但问题是,它是在WebSecurity配置之后初始化的

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

zysjyyx41#

一种方法是使用 @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();
    }

}

顺便说一下,当您排除路径时,spring security不能将安全头添加为响应的一部分。如果希望这些端点受到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();
    }

}

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

tjjdgumg

tjjdgumg2#

jzheaux提供的解决方案有效
还有一个解决方案-使用应用程序上下文getbeanswithannoation

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

        }

相关问题