【问题标题】:Spring security ComponentScanSpring 安全组件扫描
【发布时间】:2018-11-06 23:10:58
【问题描述】:

我有一个使用 Spring Security 的角色授权的 Spring Boot 应用程序。包括自定义过滤器在内的安全设置和配置存储在单个包内的 common 模块中。要在我的应用程序中使用来自common 模块的其他包,我需要使用@ComponentScan 并指定要扫描的包,但如果不包含安全包,Spring 似乎仍然会注册它并实现安全配置和过滤器。这是为什么? 项目结构:

module
    |common
    |   |src/main/java
    |   |   |com.company.product.common
    |   |   |   |redis
    |   |   |   |es
    |   |   |   |spring (the security configuration)
    |main_module
    |   |src/main/java
    |   |   |com.company.product.service
    |   |   |   |ServiceMainApp.java

配置类:

package com.company.product.common.spring.configuration;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private SecurityFilter securityFilter;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.addFilterAfter(securityFilter, BasicAuthenticationFilter.class).csrf().disable();
    }
}

@Configuration
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

    @Value("${service.security.enabled:true}")
    private boolean securityEnabled;

    @Override
    protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
        return securityEnabled ? new SecuredAnnotationSecurityMetadataSource() : null;
    }
}

主类:

@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.company.product.service", "com.company.product.common.redis"})
@EnableCaching
public class ServiceMainApp {
    public static void main(String[] args) {
        SpringApplication.run(ServiceMainApp.class, args);
    }
}

【问题讨论】:

  • 通用模块的包结构是什么,消费应用中主类的包结构是什么?
  • @AndrewS,普通(spring 有安全配置):com.company.portal.common.springcom.company.portal.common.rediscom.company.portal.common.es main:com.company.portal.customer
  • @Robert 你知道了吗?

标签: java spring spring-boot spring-security


【解决方案1】:

我假设你在你的主类上使用@SpringBootApplication注解,你的包结构应该是这样的。

src/main/java/
    -> Main
        -> securitypackage
        -> all other packages

如果是这种情况,您会自动将以下注释添加到您的主目录中。

  • @EnableAutoConfiguration:开启Spring Boot的自动配置机制
  • @ComponentScan:启用@Component扫描应用所在包
  • @Configuration: 允许在上下文中注册额外的 bean 或导入额外的配置类

如您所见,通过这一注解,您实际上是将三个注解合二为一,其中包含@ComponetScan。您可以在Spring docs 上找到更多信息。

更新

如果您需要从组件扫描中排除软件包,您可以使用excludeFilters 选项。例如,如果您想排除 esspring 包中的所有内容,您可以执行以下操作。

@ComponentScan(basePackages = {"com.company.product.service", "com.company.product.common.redis"},
        excludeFilters = {
             @Filter(type = FilterType.REGEX, pattern="com.company.product.common.spring.*"),
             @Filter(type = FilterType.REGEX, pattern="com.company.product.common.es.*")})

如果@Filter 不起作用,请尝试改用@Component.Filter。希望它有效。

【讨论】:

  • 我添加了项目结构。问题是,当我指定@ComponentScan({"com.company.product.service"}) 并运行应用程序时,我收到一条错误消息,说我缺少redis 组件,但是当我添加@ComponentScan({"com.company.product.service", "com.company.product.common.redis"}) 时,我没有收到错误消息,这意味着Spring不会自动扫描通用包中的所有内容。
  • @SpringBootApplication 注释的问题在于它只会扫描其包内的包。所以,以上级别的将不会被扫描。如果您希望它使用@SpringBootApplication 扫描所有内容,则主类必须在上层,然后从那里开始。就像我发布的结构示例一样。如果不设置任何参数,此行为与 @ComponentScan 的默认行为相同。
  • 但我的问题实际上是它实现了com.company.product.common.spring中的安全设置和配置,即使我没有指定扫描它。
  • 然后,删除@SpringBootApplication 注释,改为添加@EnableAutoConfiguration@Configuration 并保留@ComponentScan 原样。
  • 但是为什么它没有扫描com.company.product.common.redis,而是扫描com.company.product.common.spring,当我添加@ComponentScan({"com.company.product.service"})时呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 2014-07-07
  • 2019-02-16
相关资源
最近更新 更多