【问题标题】:Enabling WebSecurityConfigurer via @Profile does not work通过 @Profile 启用 WebSecurityConfigurer 不起作用
【发布时间】:2014-09-09 18:23:39
【问题描述】:

我认为,我有一个非常简单和基本的设置,用于在本地运行带有一些身份验证的 Spring Boot webapp。

我希望当我通过 Spring Boot 运行这个应用程序时,当我指定 local 配置文件时,我的自定义安全设置将覆盖默认行为。

mvn -Dspring.profiles.active="local" spring-boot:run

也许我指定了profiles.active 错误,但是当应用程序运行时,它仍然会吐出一个生成的密码来使用,并且似乎不允许在没有所述身份验证的情况下访问/login 路径。

我也没有看到/env 下的活动个人资料,这可能有点说明问题。

我有一个 WebSecurityConfigurer 像这样被覆盖:

@Configuration
@EnableWebSecurity
@Profile("local")
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN", "USER")
        .and().withUser("user").password("user").roles("USER");

    }
}

我的主要 @Configuration 类是您的标准 Spring Java 风格的基本配置:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

【问题讨论】:

    标签: java spring spring-mvc spring-security spring-boot


    【解决方案1】:

    我想我遇到了同样的问题。我想使用 Spring 配置文件在无、基本、表单等身份验证之间进行选择。但是,如果我将@Profile@Configuration@EnableWebMvcSecurity 放在public class WebSecurityConfig extends WebSecurityConfigurerAdapter 类上,就像它们在示例中显示的那样,基本身份验证有时会在我不需要身份验证时处于活动状态。 (这是我的应用程序类中的@SpringBootApplication

    我用WebSecurityConfigurerAdapter 代替@Configurations 制作bean 实现了我想要的(代码sn-p 在Groovy 中):

    @Configuration
    @EnableWebMvcSecurity
    class SecurityConfig {
        @Bean
        @Profile('no-auth')
        WebSecurityConfigurerAdapter noAuth() {
            new WebSecurityConfigurerAdapter() {
                @Override
                void configure(HttpSecurity http) throws Exception {
                    http.authorizeRequests().anyRequest().permitAll()
                }
            }
        }
    
        @Bean
        @Profile('default')
        WebSecurityConfigurerAdapter basic() {
            new WebSecurityConfigurerAdapter() {
                @Override
                void configure(HttpSecurity http) throws Exception {
                    http
                        .authorizeRequests()
                            .antMatchers('/').permitAll()
                            .anyRequest().authenticated()
                            .and()
                        .httpBasic()
                }
    
                @Override
                public void configure(AuthenticationManagerBuilder auth) throws Exception {
                    auth
                        .inMemoryAuthentication()
                            .withUser("user").password("password").roles("USER");
                }
            }
        }
    }
    

    【讨论】:

    • 绝对惊人
    【解决方案2】:

    第二次尝试更好地控制安全设置。控制安全自动配置的高级选项是什么:

    • 完全永久关闭安全性:
      • 从类路径中删除 Spring Security
      • 或排除安全自动配置 - @EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
    • 通过设置 security.basic.enabled=false 关闭默认的基本身份验证安全

    如果您可以完全控制安全设置、安全自动配置和弹簧配置文件的使用方式,那么控制不同的安全设置非常容易。

    @Configuration
    @ComponentScan
    public class Application {
        public static void main(String[] args) throws Throwable {
            SpringApplication.run(Application.class, args);
        }
    }
    
    @Configuration
    public class WebSecurityConfig {
    
        @Configuration
        @EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
        @ConditionalOnExpression("!${my.security.enabled:false}")
        protected static class DefaultWebSecurityConfig {
        }
    
        @Configuration
        @EnableAutoConfiguration
        @EnableWebMvcSecurity
        @Profile("local")
        @ConditionalOnExpression("${my.security.enabled:false}")
        protected static class LocalWebSecurityConfig extends WebSecurityConfigurerAdapter {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .authorizeRequests()
                        .antMatchers("/", "/home").permitAll()
                        .anyRequest().authenticated();
                http
                    .formLogin().loginPage("/login").permitAll().and()
                    .logout().permitAll();
            }
    
            @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth
                    .inMemoryAuthentication()
                        .withUser("user").password("password").roles("USER");
            }
        }
    
    }
    

    在上面的类中,我基本上从Application 类中删除了@EnableAutoConfiguration,以便有条件地使用它。创建了两个配置类,DefaultWebSecurityConfigLocalWebSecurityConfig,它们由 my.security.enabled 标志使用 Boot @ConditionalOnExpression 选择。

    如果我的安全性未启用,第一个配置会简单地排除 SecurityAutoConfiguration。第二个启用安全性并使用local 配置文件。通过使用不同的配置文件创建另一个配置,您可以控制不同配置文件发生的情况。然后您可以选择是否启用安全性以及使用哪个配置文件:

    #java -jar build/libs/gs-securing-web-0.1.0.jar
    #java -jar build/libs/gs-securing-web-0.1.0.jar --spring.profiles.active=local --my.security.enabled=true
    

    如果您有使用 application.yml 的选项,则可以为每个配置文件自动应用不同的设置,但仍定义默认值。如果您只想禁用默认安全自动配置启用的默认基本身份验证,这会很好。

    security:
        basic:
            enabled: false
    ---
    spring:
        profiles: local
    security:
        basic:
            enabled: true
    ---
    

    可能有上百万种不同的方法可以做到这些,而且总是根据具体情况,最适合当前的用例。

    【讨论】:

    • 这正是我想要的正是,感谢您抽出宝贵时间研究这个!
    • 第二个@ConditionalOnExpression("${my.security.enabled:false}")真的应该是真的吗?
    【解决方案3】:

    maven 将生成一个新进程来运行启动应用程序,它不会继承您传递给 mvn 命令本身的 -Dspring.profiles.active="local"

    为什么不直接构建 boot fat jar,然后将其作为可执行 jar 手动运行,然后您可以控制传递给程序的命令行参数。

    除此之外,Spring Boot 参考文档在安全章节中提到:

    如果 Spring Security 在类路径上,则默认情况下 Web 应用程序将在所有 HTTP 端点上使用“基本”身份验证是安全的。

    所以我只是用Securing a Web Application Guide 尝试了这个,如果我添加了你在问题中写的内容,应用程序在使用不活动的配置文件时默认为基本身份验证。

    @EnableAutoConfiguration 允许您为自动配置类定义排除项,但您需要找到一种方法将其与配置文件一起禁用。所以可能将@EnableAutoConfiguration 包装在两个不同的@Configuration 类中,这些类由不同的配置文件启用,这样其他的就会排除安全自动配置。

    我们在框架本身中所做的(以更复杂的方式)是使用@Conditional,它提供了更好的方式来启用/禁用部分自动配置。

    【讨论】:

    • 我在application.properties中指定@ActiveProfilesspring.profiles.active时也是这样吗?同样的问题也存在于那些集合中。
    • 确实更新了我的答案,所以让我们知道您的想法。您还可以在功能方面说出您在此处追逐的内容,以便我们可以提供更好的帮助;)
    • 我想最终我只是想在本地运行时向基本身份验证添加一些额外的设置(如formLogin 和上面指定的其他内容)。但是,我想使用具有不同安全设置的不同配置文件在非本地系统(dev/qa/staging/prod)中运行。我不确定那部分是否重要。我在这里走正确的道路吗?到目前为止谢谢!
    • 我实际上完全禁用了 Boot 提供的基本身份验证,现在它似乎可以正常工作。这是完成此任务的正确方法吗?
    • 给我一些时间。昨天我实际上正在做一些启动安全性的工作,以便在 Spring Hadoop 中为安全性准备一些其他的东西。我实际上有一个类似的问题,所以我只是在咨询我的安全/启动 Spring ninjas。
    猜你喜欢
    • 2012-05-04
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 2015-07-09
    • 2012-06-04
    • 2021-07-16
    • 2013-11-09
    • 1970-01-01
    相关资源
    最近更新 更多